Deploying a COM Addin in 64-bit Office

Deployment alone is a hassle for VSTO Developers, especially beginners. In this, if one needs to deploy add-in in a 64-bit system is hectic. Here is a simple solution that I have used to debug and deploy add-ins in 64-bit Office.

You just need to follow these steps.
By default, the add-in will be registered with the respective office application. This is enough to run the application in debug mode. If we select ‘my add-in should be available to all users…’ option, it registers the add-in in the 32-bit global registry. This can be seen in RegEdit like this.
HKLMSoftwareWow6432NodeMicrosoftOffice\AddIns

But, 64-bit Office cannot see registries in this location. For the add-in to load correctly, the registry keys should be moved to the following location.
HKLMSoftwareMicrosoftOffice\AddIns

For deploying the application…

In Visual Studio 2010, you just need to update the TargetPlatform property to x64 in the Setup Project Properties. Your project is ready to be deployed in 64-bit versions of Office now!

If you are working on Visual Studio 2008, there is a bug in setup project which prevents the add-in from registering 64-bit COM components. A work around is suggested for this problem in Cannot load 64-bit self-registering DLL’s section in Troubleshooting Windows Installer Deployments article in MSDN. It describes how to manually write 64-bit registry keys for making your add-in to work in 64-bit Office.

For more details, go through this article: Deploying COM Add-ins for 64-bit Office using Visual Studio

Check for application updates programmatically using ClickOnce Deployment

By default, ClickOnce provides two ways to update the application after installed in the client.

  1. Check everytime when the customization runs
  2. Check at regular intevals

ClickOnce Deployment Update Options
Default update types in ClickOnce Deployment

With the above, the user has to wait till it completes checking for the updates every time when the customization is loaded or at some time interval. It will be a waste of time for the users if application does not  update builds frequently.
How it would be if we provide a button for checking for updates when the user wish to do?
Hmm… Do you think that this is a headache process and hard to implement?
But, NO!
Here are the quick and simple steps to do this.

  1. Create a Windows Forms Application
  2. Place a button and call the following code. (It will check for updates and install them for you when the button is clicked)
Private Sub InstallUpdateSyncWithInfo()
    Dim info As UpdateCheckInfo = Nothing
    If (ApplicationDeployment.IsNetworkDeployed) Then
        Dim AD As ApplicationDeployment = ApplicationDeployment.CurrentDeployment
        Try
            info = AD.CheckForDetailedUpdate()
        Catch dde As DeploymentDownloadException
            MessageBox.Show("The new version of the application cannot be downloaded at this time. " + _
                                       ControlChars.Lf & ControlChars.Lf & "Please check your network" + _
                                       "connection, or try again later. Error: " + dde.Message)
            Return
        Catch ioe As InvalidOperationException
            MessageBox.Show("This application cannot be updated. It is likely not a ClickOnce application." + _
                                      "Error: " & ioe.Message)
            Return
        End Try
        If (info.UpdateAvailable) Then
            Dim doUpdate As Boolean = True
            If (Not info.IsUpdateRequired) Then
                Dim dr As DialogResult = MessageBox.Show("An update is available. Would you like to " + _
                                                 "update the application now?", "Update Available",
                                                 MessageBoxButtons.OKCancel)
                If (Not System.Windows.Forms.DialogResult.OK = dr) Then
                    doUpdate = False
                End If
            Else
                ' Display a message that the app MUST reboot. Display the minimum required version.
                MessageBox.Show("This application has detected a mandatory update from your current " & _
                    "version to version " & info.MinimumRequiredVersion.ToString() & _
                    ". The application will now install the update and restart.", _
                    "Update Available", MessageBoxButtons.OK, _
                    MessageBoxIcon.Information)
            End If
            If (doUpdate) Then
                Try
                    AD.Update()
                    MessageBox.Show("The application has been upgraded, and will now restart.")
                    Application.Restart()
                Catch dde As DeploymentDownloadException
                    MessageBox.Show("Cannot install the latest version of the application. " & ControlChars.Lf
                                              & ControlChars.Lf & "Please check your network connection," + _
                                               " or try again later.")
                    Return
                End Try
            End If
        End If
        End If
End Sub

Now say, Ain’t this cool? 🙂
Reference: http://msdn.microsoft.com/en-us/library/ms404263.aspx
Hope this helps!

Common mistakes while installation and deployment of PIAs

Have you ever came across this error message while deploying PIAs along with your add-in as prerequisites?
Problem:

Error 1316: Setup cannot read from file {PATH}PIARedist.MSI. Check your connection to the network, or CD-ROM drive. For other potential solutions, see SETUP.CHM.

Reason:
This error occurs if the PIA’s already installed in the client system. This usually happens with Office 2007 if Outlook is installed with Contact Manager.
Business Contact Manager for Outlook 2007 installs the PIAs by default, and the file name is PIARedist.MSI.  However, the file from the Microsoft Download Center is called o2007pia.msi.  When you install the PIAs from the Microsoft Download Center, this name conflict causes the 1316 error.
Solution:
The simplest solution is to just ignore the error, because this message means that the PIAs are already installed. If you want to correct the error, uninstall the PIAs through the list of installed programs for the specific computer. Then you can reinstall the PIAs with the Primary Interop Assemblies for the 2007 Microsoft Office system from the Microsoft Download Center.
For more details, refer to Misha’s article in her blog.
http://blogs.msdn.com/b/vsto/archive/2008/05/20/common-pitfalls-during-pia-deployment-and-installation.aspx

Setting up bootstrapper package of Microsoft Office Primary Interop Assemblies (PIA) to use as prerequisite for setup project

This is the procedure to set Office Primary Interop Assemblies as prerequisites to your setup project.
First, You need to download the sample of component checker sample (ComponentChecker.cpp) from this MSDN page. http://msdn.microsoft.com/en-us/library/bb332051(office.12).aspx
Please go through “Preparing the Office Component Check” section in this article. Then follow these steps.

  1. Open the Command Prompt window needed to compile the check.If you are using Visual Studio 2008, open the Visual Studio 2008 Command Prompt by clicking Start, and then pointing to Programs, pointing to Microsoft Visual Studio 2008, pointing to Visual Studio Tools, and then clicking Visual Studio 2008 Command Prompt.
  2. At the command prompt, change the directory to {SamplesDir}projectsChecks
    By default, the SamplesDir directory is C:Program FilesMicrosoft Visual Studio 2005 Tools for Office SE ResourcesVSTO2005SE Windows Installer Sample Version 3.
  3. Compile the component checker by typing the following command
    cl.exe /Oxs /MT /GS ComponentCheck.cpp advapi32.lib
  4. Close the Command Prompt window.
  5. Using Windows Explorer, copy the executable file ComponentCheck.exe into {SamplesDir}packagesOffice2003PIA and {SamplesDir}packagesOffice2007PIA.

To prepare the primary interop assemblies bootstrapper package, follow these steps.

  1. Download Office 2003 Update: Redistributable Primary Interop Assemblies from the Microsoft Download Center.
  2. Run the primary interop assembly installer.
  3. Accept the Microsoft Software License Terms, which gives you the right to package the primary interop assemblies as part of your installer.
  4. In Windows Explorer, open the folder to which the installer extracted the files.
  5. Copy O2003PIA.msi into the directory {SamplesDir}packagesOffice2003PIA

For more details, go through these:
http://msdn.microsoft.com/en-us/library/bb332051(office.12).aspx
http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/cd733f1a-7db3-430d-9700-92dc7bdac077/?prof=required
Hope this helps!

Code Access Security in .NET

Code Access Security is one of the powerful features of .NET but at the same time some confusion exists about its terminology and its usage. With this, I would like to make an attempt to explain some of the terminology with diagrams. This document does not explain all the details related to CAS, as lot of information already exists on the internet and only gives a jump start to Code Access Security.

The basics thing is whenever any code is being executed in managed world the .NET runtime verifies whether that code is allowed or not based on evidence and set of permissions.

Evidence

Where from the code came?

Permissions

What permissions are allowed for the code?

Basics Details

With the above basics let us explore Evidence and Permissions and other Code Access Security terminology.

Evidence

Evidence of an assembly is about its identity who it is and where it came from.

  • From where the assembly is being loaded?
  • If the assembly is downloaded from the web, what is the URL of the source directory?
  • What is Strong Name (if any)?
  • Who is the publisher (if digitally signed)?

How does System find out about this?
Codebase property of an assembly determines about its location which will result in either local directory, intranet/internet.One can get strong name and publisher details from the assembly manifest.
Once the Evidence of the assembly is gathered, the system grants some permission to this assembly.
How does System find out what permissions an assembly can have?
Time to explain some more terms. Let’s try to understand the following.

Policy Levels

.NET runtime security has 4 policy levels viz., Enterprise, Machine, User, and AppDomain. (which can be done programmatically).
Each policy has multiple code groups and multiple permission sets.

Code groups

Code group is a group of assemblies which satisfies the same condition. A code group will have one member condition which decides about particular assembly can be a member of this (group) or not.

Permissions and Permission Sets

Permission is what the code can do with a particular resource like File, Registry etc., and Permission Set is collection of permission.
.NET Default Policies will be

Now, we understood Policy Levels, Code Groups and their Permissions. It is time to find out how the system assigns the permissions to the loaded assembly.
Below is pseudo code how .NET Security system grants the permission to the assembly (Assumes no programmatic security)

public PermissionSet GetPermission(Assembly asm )

{

foreach( PolicyLevel pl in System.Security.Configuration.PolicyLevels )

{

foreach( CodeGroup cg in pl.CodeGroups )

{

if( cg.MembershipCondition exists in asm.Evidence )

{

// In given level it is the UNION of permissions across code groups

permissionSet[pl] = permissionSet[pl] Union cg.PermissionSet;

}

}

}

// Across levels it is intersecion of permissions

finalPermissionSet = permissionSet[“Enterprise”] Intersecion permissionSet[“Machine”]  Intersecion permissionSet[“User”];

return finalPermissionSet;

// Assume Exclusive and LevelFinal are not set

}

From above the .NET Security system assigns the permission set to the assembly.
At this point system has assigned the permission to the assembly

How does it get enforced?
The .NET classes ( System.IO.File , Microsoft.Win32.Registry classes will do the rest ) will enforce this by calling to appropriate security class.
Lets’ see how the File.OpenText code does this.

Pseudo code for OpenText()

{

string[] pathList = new string[1];

pathList[0] = pathToOpenFile;

new FileIOPermission( FileIOPermissionAccess.Read,pathList).Demand();

}

The call to .Demand will check the permission and throw an exception if it is not permitted to open the file.
If you have call to unmanaged dll where you open the text file the .NET will not be able to check whether you have permission to open or not.

Exclusive

Each code group in a policy consists of one property called Exclusive which means don’t consider any other permissions in that policy.
Lets’ walk through this…
Suppose your assembly belongs to Code group A, Code Group B and Code group C in Machine Policy.

Machine Policy

Code Group A

Permission Set A

Code Group B

Permission Set B

Code Group C

Permission Set C

And ‘Assembly Z’ falls in all code groups. Then permission set in this policy will be
Machine Level Policy for Assembly Z = (Permission Set A)   U (Permission Set B)  U (Permission Set C)  
But if set Exclusive property True in Code Group B then permission set in Machine Policy will be
MacineLevel Policy for Assembly Z =  ( Permission Set B )
Note: Still the final permission set will be intersection of Enterprise, Machine and User.
The exclusive property in .NET Configuration tool will be having check mark as


Level Final

There is another property called Level Final when checked, On Code Group, the policy in the next level will not considered.
Lets’ walk through this…

Enterprise Policy

Code Group

All_Code

Permission E

Machine Policy

Code Group

All_Code

Code Group A

Permission Set_A

Code Group B

Permission Set_B

Code Group C

Permission Set_C

User Policy

Code Group

Code Group 1

Permission Set_1

Code Group 2

Permission Set_2

Code Group 3

Permission Set_3

Suppose if an assembly belongs to All_Code in Enterprise, Code Group A,B,C in Machine and Code Group 1,2,3 in User then
Final Permission set = (Permision E) Intersection (Permision_A U Permission_B U Permission_C) Intersection (PermissionSet_1 U PermissionSet_2 U PermissionSet_3)
With Final Property set on Code Group B in Machine Policy then User Policy will not be evaluated and hence.
Final Permission set = (Permision E) Intersection ( Permision_A U Permission_B U Permission_C )
In .Net Security Configuration tool the Level Final property will be shown like below

With Exclusive and Level Final property one can precisely control the permission set applied to an assembly.

Deployment Image Servicing Management (DISM)

DISM is a new command line tool which was introduced in Windows 7 for deployment. DISM can be used to service a Window image or to prepare a Windows Pre-installation Environment (Windows PE) image. DISM also supports more features and functionality than the other tools (Package Manager) supported in Windows Vista, including logging, inventory commands with parse-able output, detailed help, offline INF driver package installation, direct application of MS update packages, and integration of international settings.

  1. Introduction to Deployment Image Servicing & Management (DISM)
    Deployment has a new tool in Windows 7: DISM (Deployment Image Servicing and Management). DISM is a command line tool which can be used to service a Windows® image or to prepare a Windows Preinstallation Environment (Windows PE) image. It replaces Package Manager (pkgmgr.exe), PEimg, and Intlcfg that were included in Windows Vista®. Read More
  2. Mounting a Wim Image for Offline Servicing
    Deployment Image Servicing and Management (DISM) is a tool which allows you to service your images offline. It supports both .wim and .vhd formats. In this article, we will look at how do you mount an Wim Image using this tool! Read More
  3. Adding or Removing Drivers from an offline Image
    You can offline service an image using DISM and add drivers to the mounted ones. You will need to download driver packages from OEM’s and ISV’s. These packages need to be INF-based packages (.exe or .msi driver installation is not available offline). Read More
  4. Enable/Disable Features using DISM on an offline Image
    You can offline service an image using DISM and enable/disable a feature on the mounted ones. In this short article, let us see on how we can do the same. Read More
  5. Unmount and clean a Wim Image using DISM Commands
    DISM provides you an option to load Wim images onto your local drive and the service it offline. You can either add/remove a driver, enable/disable features, perform other customizations.. without even installing them on a physical box. Now when you have mounted a Wim image, its really necessary to check if the image is mounted correctly. you can do that by running the command, dism /get-MountedWiminfo. Read More

Deploying VSTO 2005 Solutions

Back to (g)olden days… Here are some links which helps in deploying VSTO 2005 Add-ins. If you know some more, please add them in the comments. Thanks!
Whitepapers
Deploying Visual Studio 2005 Tools for Office Solutions Using Windows Installer (Part 1 of 2)
http://msdn.microsoft.com/office/default.aspx?pull=/library/en-us/odc_vsto2005_ta/html/OfficeVSTOWindowsInstallerOverview.asp
Deploying Visual Studio 2005 Tools for Office Solutions Using Windows Installer: Walkthroughs (Part 2 of 2)
http://msdn.microsoft.com/office/default.aspx?pull=/library/en-us/odc_vsto2005_ta/html/OfficeVSTOWindowsInstallerWalkthrough.asp
Documentation
VSTO Security MSDN documentation
http://msdn2.microsoft.com/en-us/k64zb6we(VS.80).aspx
VSTO Deployment MSDN documentation
http://msdn2.microsoft.com/en-us/hesc2788(VS.80).aspx
Security and Deployment walkthroughs
http://msdn2.microsoft.com/en-us/library/ms404813.aspx
Visual Studio 2005 Bootstrapper
http://msdn.microsoft.com/msdnmag/issues/04/10/Bootstrapper/
VSTO Outlook add-in architecture
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odc_vsto2005_ta/html/Office_VSTOOutlookAdd-inArchitecture.asp

Tools
PSS VSTO Client Troubleshooter
http://go.microsoft.com/fwlink/?LinkId=68531
Manifest Generation and Editing Tool (Mage.exe)
http://msdn2.microsoft.com/en-us/library/acz3y3te.aspx
VSTO Application Manifest Editor Sample
http://msdn.microsoft.com/office/default.aspx?pull=/library/en-us/odc_vsto2005_ta/html/Office_vstoApplicationManifestEditor.asp

VSTO in Visual Studio 2010

I am just trying to put my hands into VSTO in VS 2010. This is just an overview of that based on Saurabh Bhatia`s PDC Presentation. Some important points are briefly discussed in this post. Have a look.
One of the biggest hurdles with VSTO is deployment.
As you probably know, the pre-requisites for running a VSTO app (even of the simplest Hello World variety) include:

  • .NET Framework 3.5
  • Primary Interop Assemblies (PIAs)
  • VSTO Runtime
  • (Plus Office of course)

Now, packaging these isn’t the issue, since the Visual Studio team have worked hard to make the ClickOnce process a simple and seamless experience. The issue is the size of the download, plus requiring Admin privileges on the box you are installing on. For developers like you and me this doesn’t sound like much of a problem, but for an IT Manager in charge of rolling a simple VSTO app out across an enterprise this can be a significant headache (although Group policy can solve some of this).
And it doesn’t stop there, because if you have a number of VSTO add-ins going out, each of them needs to be installed separately. Finally there’s limitations with how to control post-install events (Eg copying Word or Excel templates into the proper locations).
The VSTO team have been focusing on deployment and security issues over the last 2 releases, and in the VS2008 release they made significant improvements. The recent SP1 for .NET 3.5 further eased the process.
But, it’s a process that still needs improvement.
Visual Studio 2010Visual Studio 2010
So, it’s good to see that the team are making excellent progress in VS2010. As the recent PDC presentation from Saurabh Bhatia demonstrated (PowerPoint file here), there’s already key functionality increases.
[UPDATE: Removed the embedded presentation as it was preloading and sucking bandwidth – click here to view]
The main points covered are:

  • Multi-project deployment (eg install an Outlook add-in, Excel add-in and Word add-in all at once)
  • Post deployment custom actions (eg moving files to user directories, deleting files during uninstall)
  • No-PIA installs (no need to include the PIAs – achieved via Type Embedding – a feature in CLR 4.0

This is welcome news to VSTO developers (actually probably more so for IT Managers). The pre-requisites are now down to the .NET Framework and the VSTO Runtime, and complex VSTO applications can be installed with a single install and enabled to configure itself.
It’d be so much simpler if the VSTO Runtime was automatically installed with Office or the Framework, but as we know, Microsoft are trying to reduce install sizes these days not add to them. Deployment will always have its pain points – good to see the team are getting close to an acceptable compromise.

Common Pitfalls during PIA Deployment and Installation

Just found the following in Mary Lee`s blog. Keeping it here hoping that it would reach more people who are in need of it.

Deploying or installing the Office primary interop assemblies (PIAs) can sometimes be problematic. There are several common errors that occur when you try to deploy or install the PIAs.

Deployment pitfalls

A. Can I deploy the PIA DLL with my setup project? Yes, you can include the PIA DLL in your setup project, but we recommend that you use the Primary Interop Assemblies for the 2007 Microsoft Office system redistributable file from the Microsoft Download Center.  this way, the installer copies the PIAs into the GAC, and also installs binding redirects.  The binding redirects ensure that the latest version of the PIAs on the computer are always loaded.  This is how a solution developed for Microsoft Office 2003 still works on the 2007 Microsoft Office system.

Installation pitfalls

A. Do you have administrator privileges? The account used to install the PIAs must have administrator privileges.

B. Is the .NET Framework already installed? The computer must have a version of the .NET Framework installed (version 1.1, 2.0, 3.0, or 3.5) before the PIA installer is run. Windows XP does not include any version of the .NET Framework unless .NET 1.1 was downloaded from Windows Update. Windows Vista does include a version of the .NET Framework. When Microsoft Office is first installed, the .NET Framework installation is detected and the PIAs are automatically installed.

C. Is Business Contact Manager installed? If Outlook 2007 with Business Contact Manager is already installed on the computer, you may see the following error message when you install the Primary Interop Assemblies for the 2007 Microsoft Office system from the Microsoft Download Center:

Error 1316: Setup cannot read from file {PATH}PIARedist.MSI. Check your connection to the network, or CD-ROM drive. For other potential solutions, see SETUP.CHM.

Business Contact Manager for Outlook 2007 installs the PIAs by default, and the file name is PIARedist.MSI.  However, the file from the Microsoft Download Center is called o2007pia.msi.  When you install the PIAs from the Microsoft Download Center, this name conflict causes the 1316 error.

The easiest thing to do here is to just ignore the error, because this message means that the PIAs are already installed. If you want to correct the error, uninstall the PIAs through the list of installed programs for the specific computer. Then you can reinstall the PIAs with the Primary Interop Assemblies for the 2007 Microsoft Office system from the Microsoft Download Center.

I don’t recommend that you follow the workaround posted at Error 1316 when installing Office 2007 PIA’s, which changes the name of the o2007pia.msi file to piaredist.msi and updates the product.xml to point to piaredist.msi.  If you change the name of the o2007pia.msi, anyone that installs the PIAs after you will experience the 1316 error.

If you discover other PIA pitfalls, please feel free to leave a comment or question so I can update this entry.  Thanks for reading!