Archive for July, 2010

How do I programmatically find the deployed files for a VSTO Add-In?

July 11, 2010

You can use ClickOnce deployment to install Office Add-ins for Office 2007 and Office 2010. It is very similar to deploying a desktop application, but not identical. With all types of ClickOnce deployments, you may include resources that you need to access programmatically. Files with a file extension of .xml, .mdf, and .mdb are assumed to be data and are deployed by default to the ApplicationDeployment.CurrentDeployment.DataDirectory, but non-data files will be found in the folder with the deployed assemblies.

With a non-VSTO application, you can programmatically find the location of the deployment by either accessing System.Windows.Forms.Application.StartupPath or by checking the Location of the executing assembly. With a VSTO application, the location of the executing assembly does not match the location of the deployment files.

The dll for a VSTO add-in is copied from the deployment directory into a separate location, and it is loaded by the host application from there. I would guess that this happens whenever you run the host application (such as Outlook), and this is why the Office add-in can be uninstalled, reinstalled, updated, etc., without impacting the host application. The changes don’t take effect until the host application is closed and reopened. So when you retrieve the executing assembly’s location, it points to the dll in the run location, and you can’t use that to track down the deployment files.

So how do you find the location of the deployment? You have to examine the CodeBase property of the executing assembly. This comes across as a URI, so you have to retrieve the LocalPath from the URI. It also includes the file name of the main assembly, so you have to retrieve just the directory name specifically.

Here’s the code in VB:

'Get the assembly information
Dim assemblyInfo As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()

'Location is where the assembly is run from 
Dim assemblyLocation As String = assemblyInfo.Location

'CodeBase is the location of the ClickOnce deployment files
Dim uriCodeBase As Uri = New Uri(assemblyInfo.CodeBase)
Dim ClickOnceLocation As String = Path.GetDirectoryName(uriCodeBase.LocalPath.ToString())

Here’s the code in C#:

//Get the assembly information
  System.Reflection.Assembly assemblyInfo = System.Reflection.Assembly.GetExecutingAssembly();
                    
  //Location is where the assembly is run from 
  string assemblyLocation = assemblyInfo.Location;

  //CodeBase is the location of the ClickOnce deployment files
  Uri uriCodeBase = new Uri(assemblyInfo.CodeBase);
  string ClickOnceLocation = Path.GetDirectoryName(uriCodeBase.LocalPath.ToString());

When you compare these values for a non-VSTO ClickOnce application, the directories are the same. When I run this code for my Outlook Add-In, I get these values:

assemblyLocation =

C:\Users\Robin\AppData\Local\assembly\dl3\VBJZ5WH8.6NJ\HRZA3JXN.LVG\b0520efe\3a5b99ef_2e21cb01\GoldMail Outlook Add-In.DLL

ClickOnceLocation =

C:\Users\Robin\AppData\Local\Apps\2.0\ZMBZ82EH.TDG\WHXVWE4L.GZ7\gold..vsto_7a251ffffc558391_0002.0000_10ff9c34a357cc30

If you’ve ever looked at the ClickOnce cache, the ClickOnceLocation will be familiar to you, being in the same format as and location as other types of ClickOnce applications.

So the assemblyLocation is where the dll is actually being run from by the hosting application (Outlook in this case), and the ClickOnceLocation is the location of the other deployment files. Any files that you deploy with your VSTO add-in and want to access programmatically can be found there.