Deploying your VSTO Add-In to All Users (Part II)


UPDATE March 11, 2010: Office 2010 does support deploying managed add-ins to HKLM which makes the below article a little bit outdated nowdays. There is also an optional download for Office 2007 containing the same fix. Check this article out for more details.


In this post I am going to discuss how the observations made in the previous post can be incorporated into a setup project for Office 2007 Add-Ins. As with any setup we will need to address installation, un-installation and repair procedures.


  • Upon the installation of Add-In we will write registry keys that are similar to what testpropagation_create.reg file from the previous post contained. This installation will contain the Create instruction telling Office propagation mechanism to copy the registry key into HKCU profile.
  • During the uninstall, we will replace the Create instruction with Delete instruction which will cause Office to delete the corresponding registry key in HKCU hive. We will also bump up Count registry value to tell Office that the instruction needs to be carried out.
  • During the repair we will need to increase Count value. This will cause Office to copy over the registry values from HKLM into HKCU.

Let’s first take care of the installation of the required registry keys. The easiest way to achieve this is by slightly modifying the default setup project that is created alongside the regular VSTO 2005 SE project. Let’s create a new Excel 2007 Add-In called “MyAddIn”. You will notice that in addition VSTO has also created a companion MyAddInSetup project. Let’s open the Registry view and clear out all the registry entries that have been created for you (i.e. completely clear the contents under HKEY_CURRENT_USER). Now we are going to import the registry information as presented below. To achieve this you will need to copy the below lines into a .reg file, then right-click on “Registry on Target Machine” node, select “Import …” and import the .reg file you have just created (notice that first you might want to adjust the highlighted strings for your particular situation).

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\12.0\User Settings\MyCompany.MyAddIn\Create\Software\Microsoft\Office\Excel\Addins\MyCompany.MyAddIn]

“Description”=”MyAddIn — an addin created with VSTO technology”
“Manifest”=”[TARGETDIR]MyAddIn.dll.manifest”
“FriendlyName”=”MyAddIn
“LoadBehavior”=dword:00000003
“CommandLineSafe”=dword:00000001

After you complete this operation your Registry View should be very similar to this screenshot :  

image


By adding above entries into Registry View we ensure that corresponding keys will be removed when Add-In is uninstalled. I would also suggest to set Create‘s key “DeleteOnUninstall” property in the Properties Window to True to make sure it is always deleted on uninstall .


Notice that now we need to add a Count value under the MyCompany.MyAddIn key. Using the Registry View to add this value would not work because any registry keys and values added through this view will be removed on uninstall. On opposite, we need Count value not just stay when Add-In is uninstalled, but its value should be incremented.

To achieve the desired effect we will create a Custom Action that will add Count value or, in case it already exists, we will simply increment its value.

Similarly, Custom Action will create a “Delete” instruction when Add-In is uninstalled.

Below I am showing code that Darryn Lavery (who put tremendous amount of effort to design and validate all I am talking about right now) has already written for his future MSDN article on this (yeah, there will be an MSDN article with the full how-to instructions) and he kindly shared it with me and I shamelessly sharing it you, but credit sitll belongs with Darryn.

Now let’s move close and see how the particular Custom Action code could look like. First, let’s start defining a class RegisterOffice2007AddIn with a couple of private methods:


class RegisterOffice2007AddIn {


 


    #region private methods


 


    private const string userSettingsLocation = @”Software\Microsoft\Office\12.0\User Settings”;


 


    public void IncrementCounter(RegistryKey instructionKey) {


        int count = 1;


        object value = instructionKey.GetValue(“Count”);


 


        if (value != null) {


            if ((int)value != Int32.MaxValue)


                count = (int)value + 1;


        }


 


        instructionKey.SetValue(“Count”, count);


    }


 


    private string GetApplicationPath(string applicationName) {


 


        switch (applicationName.ToLower()) {


            case “excel”:


                return @”Software\Microsoft\Office\Excel\Addins\”;


            case “infopath”:


                return @”Software\Microsoft\Office\InfoPath\Addins\”;


            case “outlook”:


                return @”Software\Microsoft\Office\Outlook\Addins\”;


            case “powerpoint”:


                return @”Software\Microsoft\Office\PowerPoint\Addins\”;


            case “word”:


                return @”Software\Microsoft\Office\Word\Addins\”;


            case “visio”:


                return @”Software\Microsoft\Visio\Addins\”;


            case “project”:


                return @”Software\Microsoft\Office\MS Project\Addins\”;


            default:


                throw new Exception(applicationName + ” is not a supported application”, null);


        }


    }


 


    # endregion


 


The code above contains helper method IncrementCounter that is responsible for correctly updating the Count registry value. GetApplicationPath helper method returns application-specific path Add-Ins registration key. Now, we are ready to move to the top-level function that will be called during Install and Repair:


 



public void RegisterAddIn(string addInName) {


    RegistryKey userSettingsKey = null;


    RegistryKey instructionKey = null;


 


    try {


        userSettingsKey = Registry.LocalMachine.OpenSubKey(userSettingsLocation, true);


 


        if (userSettingsKey == null) {


            throw new Exception(“Internal error: Office User Settings key does not exist”, null);


        }


 


        instructionKey = userSettingsKey.OpenSubKey(addInName, true);


 


        if (instructionKey == null) {


            instructionKey = userSettingsKey.CreateSubKey(addInName);


        } else {


            // Remove the Delete instruction


            try {


                instructionKey.DeleteSubKeyTree(“DELETE”);


            } catch (ArgumentException) { } // Delete instruction did not exist but that is ok.


        }


 


        IncrementCounter(instructionKey);


    } finally {


        if (instructionKey != null)


            instructionKey.Close();


        if (userSettingsKey != null)


            userSettingsKey.Close();


    }


}


In the above method, we first make sure the “Delete” instruction is gone and then we increment the Counter value. Notice that “Create” instruction is not explicitly installed by the Custom Action – this is handled by the installer automatically because of our previous work with the Register View.

And, finally, the function that will be called during uninstall:


public void UnRegisterAddIn(string applicationName, string addInName) {


    RegistryKey userSettingsKey = null;


    RegistryKey instructionKey = null;


    RegistryKey deleteKey = null;


 


    try {


        userSettingsKey = Registry.LocalMachine.OpenSubKey(userSettingsLocation, true);


 


        if (userSettingsKey == null) {


            throw new Exception(“Internal error: Office User Settings key does not exist”, null);


        }


 


        instructionKey = userSettingsKey.OpenSubKey(addInName, true);


 


        if (instructionKey == null) {


            instructionKey = userSettingsKey.CreateSubKey(addInName);


        } else {


            // Make sure there is no Create instruction


            try {


                instructionKey.DeleteSubKeyTree(“CREATE”);


            } catch (ArgumentException) { } // Create instruction did not exist but that is ok.


        }


 


        string instructionString =


                        @”DELETE\” +


                        GetApplicationPath(applicationName) +


                        @”\” +


                        addInName;


 


        deleteKey = instructionKey.CreateSubKey(instructionString);


 


        IncrementCounter(instructionKey);


    } finally {


        if (deleteKey != null)


            deleteKey.Close();


        if (instructionKey != null)


            instructionKey.Close();


        if (userSettingsKey != null)


            userSettingsKey.Close();


    }


}


This is pretty much it. Assuming you have already experimented with SetSecurity Custom Action you should be able to wrap this code into a Custom Action DLL, set CustomActionData properties as /addinName=”MyCompany.MyAddIn” /application=”Excel” (again choose the value that fit your particular case), and invoke the above methods on Install, Uninstall and Rollback. I will try to sum it all up in another post though.

Comments (89)

  1. Hi Misha

    Can you recap on the reasoning behind the steps?

    1. Create a reg file to add the master key

    2. Add a custom action to increment / decrement the Count – this causes the already installed key to refresh on install / repair

    Can I create the reg key within the setup program, rather than using a reg file?

    Thanks

    Ken

  2. Ken,

    Re 1: Why "create a reg file to add the master key"

      There is no particular reason besides my preference. I could have said "go and add this key and these values through the designer", but for some reason I just felt it might be simplier for everyone if I said "copy&past these values, modify them and import them into your project", this is especially true because copying from an existing script make it much harder to miss things.

    Re 2: Why "Add a custom action to increment / decrement the Count – this causes the already installed key to refresh on install / repair"

      Office compares HKLM’s Count value against one stored under HKCU…Office12.0User Settings<MyAddin>. The instructions will be carried out only if those values are different, then Office copies the new Count under HKCU…Office12.0User Settings<MyAddin> as a form of optimization to avoid carrying the same copy/delete instruction on every boot. Hence, Count value needs to stay even after add-in is uninstalled. When a registry value is authored through MSI tables – it will be cleaned up during the uninstall and the only way to achieve the desired behavior is to write a Custom Action that will managed the Count value.

    Why some registry keys are added through Registry View and others are added/modified by Custom Action?

    My approach has been:

    1. The registry keys managed by the MSI tables are those that need to be added during installation/repair and removed during uninstall.

    2. The registry keys managed by the Custom Actions are those that Windows Installer rules install/uninstall rules can not be applied to.

    You can do things differently, of course, and have your Custom Action managed all your registry keys instead.

  3. Jie says:

    A Simplified Chinese version of this aritcle: http://blog.joycode.com/vsto/archive/2007/09/16/108546.aspx

    Xie Xie Misha! 🙂

    感谢 Misha 允许我把此文翻译成中文。

  4. George says:

    Hi Misha,

    Can you please explain what ‘Properties Window’ you meant in the following paragraph:

    By adding above entries into Registry View we ensure that corresponding keys will be removed when Add-In is uninstalled. I would also suggest to set Create’s key “DeleteOnUninstall” property in the Properties Window to True to make sure it is always deleted on uninstall.

    Thanks,

    George.

  5. Oh, I just meant the "Properties" Window – the one that shows and allows browsing properties of the currently selected object. In the Registry View, you can right click on the reg key, select "Properties Window" and it will show a little window where one of the things you can modify is "DeleteOnUninstall". On my machine the window shows up in the right lower corner of the VS IDE.

  6. Ignacio says:

    Hi Misha,

    I’am deploying my own vsto application and I’am trying to give the option to choose the kind of installation for the current user or all the user. Now Im trying to use a variable in the condition property of the key but it did’t work. What can I do?

    Thanks,

    Ignacio.

  7. Ignacio,

    First, you would need to undersand why it did not work. Windows Installer has some logging capabilities that might help you out – check out the command line options for msiexec.

  8. Kulvinder says:

    Hi Misha,

    For Windows Vista 64 bit (if elevated security i think), Outlook 2007 doesnt load addins created having details under HKCU. The registry information (under Software) has to be under HKLM.

    Can you write something on Vista 64 Bit and Outlook 2007 ?

    Thanks

  9. Shawn Mullen says:

    Automatic updates are great.  I wished it actually worked.  Has anyone addressed the fact that most companies do not allow their users to download dlls over http.  If there is a solution to this using VSTO 2005 SE, please let me know, but as far as I can see there isn’t one.  So, I now have to use a third party updater to make this work (I don’t feel like writing my own).  

  10. A simpler way to handle this, especially if your add-in is build for 2003 and later, is to simply not include the "Manifest" key in the registry.  This will cause Office to use the AddinLoader shim.  The downside being that you no longer have the "native" support in 2007, but you do simplify your installer and the maintenance there of.

  11. BJ,

    You are correct – but only half way. Only pure managed add-ins have support for some of the Office 2007 features such as CustomTaskPanes and Ribbons. Once you start using these VSTO features you really need this "Manifest" reg value.

  12. Markus Jerneborg says:

    Thank you for a good post Misha. It helped me tons.

  13. Jason says:

    There are one problem.

    Regist Addin like that cause a question, when Office2003 started, it also load this addin.

    How Can I Fix it?

    Thanks

  14. Jason,

    I am sorry. I tried to understand your question but I could not figure out what you are trying to say. Can you rephrase what is the problem you are seeing?

  15. Eine wesentliche Limitierung von managed Office 2007 Add-Ins ist die Beschränkung auf eine per-User –

  16. Eine wesentliche Limitierung von managed Office 2007 Add-Ins ist die Beschränkung auf eine per-User

  17. I have the Create/Delete command pattern down.  And on the surface everything works.   But I notice several problems:  ( this is a VSTO 2008 .vsto not VSTO 2005 .manifest )

    1) The first time a user starts word it asks them if the want to install the add-in.  If they click yes everything is fine.  If they click no, they are never asked again.   The only way to get it to ask them again is tweak the HKLM Count value to cause it to be repropagated to HKCU for Winword to see again.

    2) When they click yes:

    a)  registry entries get created by vstoinstaller in HKCUSoftwareMicrosoftVSTA and VSTO keys.   They are guids and different everything it runs.  I’m not sure what drives this.

    b) an entry is added to add/remove programs for the user. ( undesired )

    3) when I uninstall the application the delete key properly removes the addin the next time word is run but the VSTA, VSTO and Add/Remove resources linger on the machine.

    4) I’ve not tested upgrade scenarios yet.

  18. Joe says:

    Hey Misha,

    That may look irrelevant, but I have a vista machine with OL2007, and I’m installing a VSTO setup for OL2007 and I have serious troubles reading and writing to registry. I’m using pretty much straight forward commands like:

    Registry.SetValue() and Registry.GetValue()

    I event tried Registry.LocalMachine.CreateSubKey() and none seems to be working so I realized that is an issue with vista.

    Please let me know what do I have to do with vista machines that runs OL2007?

    Thank you!

    Joe

  19. Gábor Vas says:

    Cristopher Painter:

    When the manifests are signed with a certificate from the Trusted Publishers certificate store, and that certificate is certified directly or indirectly with a certificate from the Trusted Root Certificate Authorities certificate store, then ClickOnce won’t ask the users for trust.

    Regarding your other problem, with Office 2007 and VSTO 3.0 you can prevent the installation into the ClickOnce cache by appending the |vstolocal suffix to the path of the deployment manifest (at the Manifest registry key). This means that there won’t be any entry in the add/remove programs for the add-in. See the following forum thread for details: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2543533&SiteID=1

  20. There are many resources to learn about Visual Studio Tools for Office, and they are scattered through

  21. Mohan Kumar K says:

    I have created an addin for Word 2007 using VSTO SE and I am trying to deploy it for All Users. I find your article very useful and it helped me to know what exactly I am missing. But the problem is I am new to .Net & very new to C#.  I couldn’t understand certain things and need your help to figure out.

    I have created a class named "RegisterOffice2007AddIn.cs" in SetSecurity Project and copied the code to that class.

    class RegisterOffice2007AddIn

    {

    #region private methods

    ….

    ..

    # endregion

    }

    I would like to know where the below mentioned function will go into that "RegisterOffice2007AddIn.cs". (I mean where exactly we need to copy this code, excuse me if this question is too naive).

    public void RegisterAddIn(string addInName)

    public void UnRegisterAddIn(string applicationName, string addInName)

    ==============================

    This is pretty much it. Assuming you have already experimented with SetSecurity Custom Action you should be able to wrap this code into a Custom Action DLL, set CustomActionData properties as /addinName="MyCompany.MyAddIn" /application="Excel" (again choose the value that fit your particular case), and invoke the above methods on Install, Uninstall and Rollback. I will try to sum it all up in another post though.

    Do we need to create new set of custom actions or can we replace the existing one created for SetSecurity project. Is there any other post which will provide more elaborate details on this.

    Any help would be much appreciated.

    Thanks,

    Mohan

  22. Mohan,

    if you look carefully at the SetSecurity sample project you can notice that SetSecurity class actually derives from System.Configuration.Install.Installer class and overrides its Install, Rollback and Uninstall methods. These are the methods that Windows Installer is actually calling – they in turn extract the parameters and call the worker method – SetSecurity. You just need to follow the same pattern here. Hope this helps.

  23. Mohan Kumar K says:

    Misha,

    I would like to know where the below mentioned function will go into that "RegisterOffice2007AddIn.cs". (I mean where exactly we need to copy this code, excuse me if this question is too naive).

    public void RegisterAddIn(string addInName)

    public void UnRegisterAddIn(string applicationName, string addInName)

    Thanks,

    Mohan

  24. Ricky says:

    Hi Misha,

    I’ve processed every step of your tutorial and it works to deploy my PowerPoint-Add-In to every user on the target machine, but there is still a problem with some Code Access Security-Stuff I think. If I login as another user on the target machine and start PowerPoint I get a popup that says "Der angeforderte Registrierungszugriff ist unzulässig." (must be the message "Requested registry access not allowed" in english).

    I also added the SetSecurity Project to my Add-In and added cutom defined actions with correct parameters. After the installation of the add-in, i have my code groups on machine-level which give the add-in full trust. What else could be wrong? Do you have any idea?

    Thanks a lot and best wishes!

    Ricky

  25. I doubt the problem it registry CAS related – probably some piece of the software tries to acces the registry and fails. I would suggest you to run regmon from http://www.sysinternals.com and check which registry entries the process tries to access. Probably this will give you some idea.

  26. Ricky says:

    It’s a piece of my code in the add-in which tries to read a value from registry. I also have a version of that add-in-code for PPT2003 which is identically with it for 2007 except for the steps to install for all users. in PPT2003 all works fine.

  27. Ricky says:

    Hi again!

    I solved my problem now by using this code to grant access to the registry-entry:

                       RegistryPermission readPerm1 = new RegistryPermission(RegistryPermissionAccess.Read, @"HKEY_LOCAL_MACHINESOFTWAREProductName");

                       readPerm1.Assert();

                       RegistryKey OurKey = Registry.LocalMachine;

                       OurKey = OurKey.OpenSubKey(@"SOFTWAREProductName", RegistryKeyPermissionCheck.Default, RegistryRights.ReadKey);                    

                       pathtoexe = (OurKey.GetValue("Path2exe").ToString());

                       clientApplicationProcessName = "PPT2Go";

                       OurKey.Close();

                       OurKey = null;

    Best wishes!

    Ricky

  28. Lily Collins says:

    Dear Misha,

    Is this the approach you would use if installing an VSTO SE Outlook 2007 add-in to a Citrix server?  I have an Outlook 2007 add-in that I am able to install without issue to individual users but the add-in won’t load with Citrix.

    Any insight you have with Citrix would be really helpful.  I have been requested to update the HKLM registry but my understanding is that any settings here are ignored for VSTO SE add-ins.

  29. Lily,

    Unfortunately I have no idea what Citrix server is. If you want to provide more details please contact me offline – use the email link at the top of this page.

  30. Inder says:

    Hi Misha,

    I read your post saying that " Office 2003 does not have a native notion of managed add-ins. So all COM add-ins (even VSTO add-ins for Office 2003) can be registered under HKLM hive (e.g. HKLMSoftwareMicrosoftOfficeExcelAddInsMyAdd) which will work for machine-wide deployment – and this is how machine wide deployment of add-ins has been done in the past."

    I tried this in office 2003 and created all registry entries under HKLM. My setup creates all required registry entries but the addin doesnt get loaded. And i am not talking about CAS yet, it doesnt even show in com addins list in word 2003.

    Does VSTO SE Addin loader ignores HKLM? How do we do machine wide addin deployment on office 2003 for addins built with VSTO SE.

  31. Office 2003 does not display HKLM registered add-ins in COM add-ins dialog. So, the fact that these do not show up does not indicate they HKLM add-ins did not load. Typically, to deploy to HKLM on Office 2003 – I would just move all the registry keys from HKCU to HKLM and modify the SetSecurity to run caspol for machine level policy.

    What happens under the cover?

    VSTO SE AddIn loader is implemented by AddinLoader.dll – this is a native DLL that knows how to handle instantiation of VSTO add-ins as if those were regular COM objects. Hint: to check whether Office 2003 picked up your addin you can check whether AddinLoader.dll has been loaded (use process explorer from sysinternals.com or just a regular native debugger to see which modules are loaded). When AddInLoader.dll is loaded into the process it has no idea whether it was registered from HKLM or HKCU. Instead, the only information it gets is the GUID of the COM Add-In. Given this information it always tries to find the .manifest file (which has information about assemblies that need to be loaded) by combinining the ManifestLocation and ManifestName registry values from HKCRCLSID{– GUID —}InProcServer32. Note that HKCR is not a real registry hive – instead it is just a virtual merge of HKLMSoftwareClasses and HKCUSoftwareClases.

    Once .manifest file is found – AddInloader would try and load the assemblies specified in the manifest.

    From this point on the loading failures can be seen using VSTO_SUPPRESSDISPLAYALERTS environment variable.

    As you can see there are multiple points of failure that can result from incorrect registration and you really need to follow the entire chain to understand what might be going on in your case. Additional points of failure are: add-in might have been soft-disabled – LoadBehavior was reset to 2, add-in might have been killed and have been hard-disabled – check the Help->About -> Disabled Items … .

    If you have further questions to do hesitate to contact me using the email link at the top right corner of this page.

  32. Angledor says:

    Hi,

    Thanks a lot for this article, it will be very useful for me.

    But I have a problem with uninstallation:

    The value ‘Count’ under my Key ‘MyCompany.MyAddIn’ is automatically removed after the uninstall!

    So uninstall of User registry Key is not done.

    – ONLY the Create’s key is set to “DeleteOnUninstall” in msi

    – In the CustomAction there is always 2 values  (Count and Order)

    But when I play the same code after uninstall, there is no value anymore!!!

    This is the code to test if the 2 values are always there:

           RegistryKey userSettingsKey = null;

           RegistryKey instructionKey = null;

           private const string userSettingsLocation = @"SoftwareMicrosoftOffice12.0User Settings";

           private const string addInName = @"Firmenich Outlook Sender Addin";

               userSettingsKey = Registry.LocalMachine.OpenSubKey(userSettingsLocation, true);

               instructionKey = userSettingsKey.OpenSubKey(addInName, true);

               Console.WriteLine(string.Format("Value Count of n"{0}\{1}" = {2}", userSettingsLocation, addInName, instructionKey.ValueCount));

    Do you have an idea of what’s happened to delete those Value in registry just after uninstall??

    This is a mystery for me.

    Thanks

  33. This post is both the continuation of part I and part II installments but it also addresses new product

  34. I got ahead of myself and thought it was one week later than it really is (sort of good because I was

  35. Phillip says:

    Hi Misha, thanks for the article. I created the propagation keys under HKLM like in the article, and they appear to be creating the HKCU keys correctly. Despite this, my add in is still only appearing on the user account that I used while installing it. It doesn’t show up on any other user accounts.

    Is there something that lists everything that is needed for an add-in to load in Outlook? I am looking for something that lists all registry keys, file locations, etc. This will let me look and see why my add in isn’t loading for all users.

    Thanks,

    P

  36. Hi Phillip,

    Most probably cause is that your SetSecurity Custom Action modifies CAS policy at the user level – for all users deployment make sure the assemblies are trusted at the machine level.

  37. Phillip says:

    Hi Misha, thanks for the quick response. I double-checked my CAS policy code and the actual CAS policy on this machine. Everything is set at the machine level. The addin has its own code group at the machine level with full trust for everything under the addin’s directory. Is there something else that I can check?

    thanks,

    P

  38. Phillip, can you contact me offline about this – use email link at the top of this page

  39. Das Office 2007 Security Modell erlaubt es nicht, unter HKLM registrierte Managed Add-Ins zu verwenden.

  40. While the default mechanism for deploying VSTO v3 Add-Ins is ClickOnce, there there’s now also a documented

  41. Rajesh says:

    This is for Outlook 2003 Addin developed using VSTO 2005.

    I have similar but not the exact problem. I am trying to deploy an outlook addin in Citrix. My setup project applies custom security policies for all users and my registry entries are for HKLM. Even so, when I deploy my addin, it is only visible for the user who installed it – no other users can see the toolbar button this addin provides. I checked to see if the addin was blocked – it is not listed in the COM Addin list.

    Any suggestions

  42. Rajesh,

    If things are the way you say they are – then there should be no problem, Citrix or not, all users on the machine should be seeing this addin.

    Get it touch with me through email link at the top of this page and I can take a quick look at your setup to see whether there is any problem with it.

  43. Paul says:

    Has Darryn Lavery created his "MSDN article with the full how-to instructions" yet? Thank you.

  44. Paul, unfortunately MSDN article did not happen. Since then Darryn decided to move on and other things took precedence for him.

  45. Paul says:

    Thank you for your response. It is a shame that the article will not be written. Oh well. I have very little experience writing custom actions, so I have a couple of questions regarding the steps you outlined above: Where exactly should the three blocks of code mentioned in this blog be written, in a class in the same project that includes the add-in class? Or should the code be written in a class library, and then the resulting dll be associated with the install, uninstall, and rollback actions? Where do I find out more about the setsecurity custom action? I do not quite understand how your code fits in with the set security custom action. Thank you, Misha. I really appreciate it.

  46. Paul,

    Take a look at Darryn’s article on VSTO 2005 SE deployment at http://go.microsoft.com/fwlink/?LinkID=57779 . It comes with a sample solution which has SetSecurity as its custom action. Basically, you need to write a simple DLL with a class deriving from System.Configuration.Install.Installer class.

    Then you need to add this project to the deployment project. I believe there are lots of tutorials how to write Custom Actions – so you will be able to find lots.

    Let me know if you are stuck and I will try to find time to respond with more detailed steps.

  47. Paul says:

    Is this the right approach?

    1. Add an installer class to the add-in project

    2  In the "Public Overrides Sub Install…" procedure, call RegisterAddIn

    3. In the "Public Overrides Sub Uninstall…" procedure,call UnRegisterAddIn

    Here is how the vb.net code in the installer class looks thus far:

    Imports Microsoft.Win32

    Imports System.ComponentModel

    Imports System.Configuration.Install

    Public Class gseWrdAsgnUserInfoInst

       Private Const userSettingsLocation As String = "SoftwareMicrosoftOffice12.0User Settings"

       Public Sub New()

           MyBase.New()

           ‘This call is required by the Component Designer.

           InitializeComponent()

           ‘Add initialization code after the call to InitializeComponent

       End Sub

       Public Overrides Sub Install(ByVal stateSaver As System.Collections.IDictionary)

           MyBase.Install(stateSaver)

           Call RegisterAddIn(Me.Context.Parameters("addinName"))

       End Sub

       Public Overrides Sub Uninstall(ByVal savedState As System.Collections.IDictionary)

           MyBase.Uninstall(savedState)

           Call UnRegisterAddIn(Me.Context.Parameters("applicationName"), Me.Context.Parameters("addinName"))

       End Sub

    These procedures are then followed by your procedures

    Do I need to call the UnRegisterAddIn procedure in "Public Overrides Sub Rollback…" as well?

    Thank you, Misha. You don’t know how much I appreciate this.

  48. karan says:

    Misha,

    Do VSTO SE addin developers for office 2003 need to worry about memory leaks of com objects used by addins especially outlook addins or is it taken care by addinloader/VSTOSE internals.

    If yes, then what is the best practice for releasing com objects? Does setting them to null suffice or marshal.releasecomobject be used instead.

    How is COM objects handled in memory by VSTO SE addins. I know that addinloader disposes all com objects held by addin(outlook, word etc) once the last instance of application is closed. But what in case the application instance is running. Does it keep on adding more and more com object refernce

  49. Hello karan,

    VSTO takes care of COM references and users do not need to call Marshal.ReleaseComObject to cause Outlook to shutdown correctly. Actually the entire premise of us doing the special VSTO loader for Outlook was to provide an easy way around known Outlook 2003 bug when managed add-ins would keep Outlook alive (see http://blogs.officezealot.com/whitechapel/archive/2005/07/10/6747.aspx).

    Sue Mosher cover VSTO-enabled add-ins quite extensively here – http://www.outlookcode.com/article.aspx?ID=42

    As to how VSTO deals with shutting down references to COM objects – we load add-ins into separate AppDomains. When add-in is closing we will unload the AppDomain which has an effect of releasing all Runtime Callable Wrappers (RCW) that live in this AppDomain.

    This is all, of course, not to say that you should never use Marshal.ReleaseComObject in your add-in. There are other issues besides shutdown that might need a call to Marshal.ReleaseComObject (unfortunately I do not do a lot of Outlook-specific development so I do not have an exact list of issues).

    But make sure to check Sue Mosher’s website.

    Hope this helps,

    Misha

  50. karan says:

    Thanks for quick response.

    I read thru the articles you provided and they are great. I understand that addinLoader in vstose releases all com held by addin when last app instance is closed.

    But what about while the addin is still running. As i keep on using my addin operations, the memory consumption keeps on inceasing for the application (word, excel etc) process hosting addin. Currently i am setting the objects to null once i am done with them. Is it better to use marshal.releaseCComObject instead.

    I tried it though but didnt see much improvement.

    Also in my addin i am adding not more than 8 menus and their event handlers invoke UI in a sepearte process. But when i see the memory consumption of application, it is more than double compared to when application is run w/o addin. This is another cause of concern.

    I am still reading through the Sue mosher’s website but didnt find anything that talks about the issues of memory management for VSTO addins.

    In Nutshell is it better to release com objects usign marshal.releasecomobject wherever possible or should it be left upto addinloader? Please let me know if you know any best practices/guidelines for this.

    I appreciate your help. Thanks Misha..

  51. While running, VSTO does not help you managed the COM interop layer. The regular managed lifetime semantics apply here: when an RCW wrapping a COM object is GC’d – the reference to the underlying COM object will be removed. Usually, CLR is good to take care of memory and unreferenced RCWs are collected regularly.

    Said that, when you are dealing COM the references management is a bit more complicated. When managed objects are exposed to COM consumers (e.g. as event sinks) – these objects become ‘rooted’ objects that are not eligible for GC unless COM consumers do not reference those objects.

    The particular issue to be aware off is circular references that might prevent collection of objects – the most common case of creating such circular reference is when you have a class that stores a reference to a COM object and subscribes to an event from this COM object – this creates a circular reference and all involved objects will never get garbage collected untill you remove the event handlers or unload the AppDomain.

    Marshal.ReleaseComObject is useful when you want to control precisely when to remove the reference to a COM object from managed code. Notice, that ReleaseComObject does not remove the RCW – it rather decrements RCW’s internal reference counter and when it drops to 0 – then when RCW will release the COM object.

    Sometimes, in well controlled cases, using RCO is useful, but overdoing it might lead to bugs like NullReferenceException.

    The most useful tool to troubleshoot memory links is SOS extension (you can use it in WinDbg or in VS while debugging native code). John Robbins has a very good book on debuggin which contains a good primer on SOS – but there are online references as well (e.g. you might want to look at Tess’ blog http://blogs.msdn.com/tess). In particular, the SOS has ‘!dumpheap -type System.__ComObject’ command which allows you to see all the RCWs, then you can pick any object and run !GCRoot command that will tell what causes this object to stay alive.

    This is probably a lot of information. So I am ready to take follow up questions 🙂

  52. lee_fuller says:

    Good morning,

    Apologies if this posting is in the incorrect area but I’m completely stumped on this problem.

    I’ve recently created a new Excel add-in using Visual Studio Tools for office and created the set-up package which installs the dlls, modifies the registry and updates the .NET security policy so the add-in can run.

    The package doesn’t seem to install fully when running on a non-admin account machine.  Even if we run the install package using ‘Run as:’ and using a admin account it still doesn’t work quite right (though there are no error messages on the install).  The dlls are installed correctly but the registry isn’t written to and the security policies

    aren’t updated.

    If I run the install package logged in directly as an administrator then it all works fine.  I would have thought using ‘Run as:’ when logged in without admin rights it would work as well but for some reason it doesn’t.

    Does you know what’s going on?  Is there some restiction on using ‘Run as:’ that doesn’t quite replicate being logged in directly as someone with Admin rights?

    Many thanks in advance,

    Lee.

  53. Lee,

    for these kinds of questions it would be helpful to know the operating system you are using, version of VSTO you are using, version of Excel you are targeting and so on.

    But here are some things to keep in mind: if your setup installs registry keys under HKCU hive – keep in mind that when you use ‘run as:’ this will install the registry keys into the HKCU hive of the user you are ‘run as’ing. Similar "redirection" happens if your setup modifies security policy at the user-level.

    On the other hand, if your setup tries to install any registry keys into HKLM registry hive – the non-admins will not be able to install these registry keys since they do not have the access.

    Also keep in mind that some pre-reqs for the setup i.e. VSTO runtime have to be installed with admin priviliges.

  54. mathjcb says:

    Hi Misha ,

    I already have an MSI in the field and do not want to push a new MSI because of the sheer number of users , I want to just create a registry patch . Is it possible to create an MSP file using OCT to do this job ?

    I was able to do that to propagate shared clip art registry entries to all users in the local machine .

    Thanks

  55. Mathjcb,

    I know what an MSP is but no idea what an OCT is though.

    Unfortunately my depth of knowledge for building patches is not there to make a possible/impossible  or right/wrong sorts of calls.

    My gut says that if you created per-user installation package it might be very hard to create a per-machine patch. But again, I might be wrong.

  56. mathjcb says:

    I came to know about OCT(office customization tool ) from a microsoft engg on a tech support call . He helped me build the .msp file that creates registry entries in HKCU as he logs in and launches office, this was done to make a clipart organizer shared to all users who log into the machine . (I do not know the underlying principle behind it , but doesn’t look like its the same as in your blog).

    Also after installing the per user installer package I was able to make it work for all users by running the below mentioned registry .

    Windows Registry Editor Version 5.00

    [HKEY_LOCAL_MACHINESOFTWAREMicrosoftOffice12.0User SettingsMyAddin]

    "Count"=dword:00000001

    [HKEY_LOCAL_MACHINESOFTWAREMicrosoftOffice12.0User SettingsAmeriprise.AdviceEditor.Word2007.EditorAddInCreate]

    [HKEY_LOCAL_MACHINESOFTWAREMicrosoftOffice12.0User

    SettingsAmeriprise.AdviceEditor.Word2007.EditorAddInCreateSoftware]

    [HKEY_LOCAL_MACHINESOFTWAREMicrosoftOffice12.0User

    SettingsAmeriprise.AdviceEditor.Word2007.EditorAddInCreateSoftwareMicrosoft]

    [HKEY_LOCAL_MACHINESOFTWAREMicrosoftOffice12.0User

    SettingsAmeriprise.AdviceEditor.Word2007.EditorAddInCreateSoftwareMicrosoftOffice]

    [HKEY_LOCAL_MACHINESOFTWAREMicrosoftOffice12.0User

    SettingsAmeriprise.AdviceEditor.Word2007.EditorAddInCreateSoftwareMicrosoftOfficeWord]

    [HKEY_LOCAL_MACHINESOFTWAREMicrosoftOffice12.0User

    SettingsAmeriprise.AdviceEditor.Word2007.EditorAddInCreateSoftwareMicrosoftOfficeWordAddins]

    [HKEY_LOCAL_MACHINESOFTWAREMicrosoftOffice12.0User

    SettingsAmeriprise.AdviceEditor.Word2007.EditorAddInCreateSoftwareMicrosoftOfficeWordAddinsMyAddin]

    "Description"="MyAddin  — an addin created with VSTO technology"

    "FriendlyName"="MyAddin"

    "LoadBehavior"=dword:00000003

    "CommandLineSafe"=dword:00000001

    "TestingModeEnable"="false"

    "Manifest"="C:\Program Files\Amp\Ampf\MyAddin.dll.manifest"

    I already had the CASPOL policy run at machine level , all I needed to do was propagate the registry to HKCU ,

    I was thinking of packaging this .reg as an MSP file using OCT , so my question .

    Appreciate your reply .

    Thanks ,

    Mathew

  57. Steffen says:

    Hi Misha,

    first let me say how much I appreciate your work on this issue!

    Would you please clarify for me some questions regarding the Custom Action?

    What I have so far is my AddIn project with a working SetSecurity project included. I’ve added your code the same way like SetSecurity. What I do not understand is, how are the functions in your code are being called during install, uninstall and rollback (btw, what’s about commit?) What do I have to fill in as CustomDataAction properties on install/uninstall/rollback/commit?

    BTW, you’ve wrote that all the automatically registry entries from the registry view should be cleared. What’s about the “Classes” section? Should they be cleared as well?

    Do you have a sample project available which is demonstrating the above topics?

    Kind regards,

    Steffen

  58. I had a great time over the last couple of days hanging out with Christen Boyd and some of the other

  59. Thomas says:

    Hi Misha,

    I have installed my add-in for Office 2003 using the method you descibed above. It works perfect. The add-in works.

    But as you mentioned also above Office 2003 does not display HKLM registered add-ins in COM add-ins dialog.

    Is there any possibility to show the add-ins in the dialog?

  60. Hi Thomas,

    > Office 2003 does not display HKLM registered add-ins in COM add-ins dialog. Is there any possibility to show the add-ins in the dialog?

    I wish I knew how to work around this.

  61. rocky says:

    hello,Misha

    I have read the article,but all is about office2007.Now I have created an addin for office2003 ,and deployed it use administrators.it does work.but when with common Users account,it doesn’t work.How can I deploy the add-in for office2003 to all user?

    kind regards

    rocky cheng

  62. Priya says:

    Hi Misha,

    When I uninstall my add-in, I am creating a Delete key. But I am not able to increment/decrement the counter while uninstalling since the counter property/value itself is not available for my add-in in registry.

    Once my add-in is uninstalled, the local machine/user settings entry for my add-in has only one property/value called default. Any idea on this behaviour?

    Thanks,

    Priya

  63. alan glover says:

    Does this article apply to Outlook 2003 if the add-in was created using VSTO 2005 SE?  It is a managed code add-in?

  64. smclewin says:

    Misha,

    Your series of articles were exceedingly helpful.  I started in writing my first Office add-in using VS2008, VSTO 3.0 and Office 2007 in January, at a time when no books were yet released for VS2008/VSTO3, most blogs talked about VSTO 2005 SE and VS2005 and I had this little problem of doing a multi-user installation of an add-in.  Thank you for that.

    I have a question about handling upgrades.

    The add-in I’ve written uses several assemblies from our in-house code library to connect to our back end system.  The add-in itself is a front for a document store product we create and allows user to edit documents and spreadsheets in Office apps.

    We install those assemblies to the GAC in the setup program – we simply could not get the add-in to find the assemblies unless they were in the GAC.

    I’m running into problems with testing upgrades to the system.

    Our deployment is such that an administrator installs the add-ins on workstations that are mult-tenant through shifts throughout the day.  On the initial install, keys properly propagate from the HKLM hive into the HKCU hive for each user.  As each user starts Word/Excel, the clickonce vsto install process happens per user.

    On uninstallation, the DELETE command is placed into HKLM, but typically we are uninstalling and then immediately installing a new version.  There is simply no guarantee that each user will log in to have the DELETE command executed.

    What I’m finding is that when the administrative account logs in, uninstalls the vsto add-in from the Add/remove Programs list, uninstalls the setup program the Add/remove programs list and then reinstalls that we have a problem.

    The add-ins work fine under the administrative account.  They won’t start for the regular users after the upgrade process.  VSTO_LOGALERTS messages cite missing assemblies as the reason.

    Are there special considerations I need to make for upgrading from one version of an add-in with satellite assemblies to the next for all users using the techniques you described here?

    Thanks for your time.  You’ve really helped with this series.

    Scott

  65. Why do we need to alter the &quot;SetSecurity&quot; and the &quot;Setup&quot; project? I sincerely suggest

  66. Len says:

    Hello there!

    I just have a question about addin deployment. With regards to the way the solution depends on the "Count" value being incremented before keys will be propagated from HKLM…"Create" to HKCU:

    – does this mean that if the user who installs an addin originally (admin) then starts an Office Application (causing the keys to be copied to their own HKCU), no other user will see the HKCU keys until a new install or repair is done?

    From what I can see, Count only gets incremented at install or repair time- does this mean that the keys will only be copied once? I.e: for the next user that starts an Offce application?

  67. Len,

    On initial installation the Count value does not need to be incremented because there is nothing to increment – it did not exist before 🙂

  68. Hey Nice approach !!!!!

    Thanks

    Aarun

  69. Mike Hatfield says:

    Hi Misha,

    Many thanks for these two articles. The processes seem to be working ok, apart from one final stumbling block I can’t seem to shift regarding common settings for both Word 2003 and 2007. (I’m using Visual Studio 2005 and VSTO 2005 SE, all on XP.)

    I understand that Word 2003 will happily load an add-ins registered at HKLMSoftwareMicrosoftOfficeWordAddins whereas 2007 wants them in HKCU. No problem and I’ve got a SetRegistry project copying the keys as described in this article.

    But, Word 2007 absolutely refuses to load my add-in if the HKLM key exists at all. Using RegMon, I can see it looking in HKLM, then HKCU, then setting LoadBehavior to "0" in HKLM. Unfortunately, this must be overwriting the valid HKCU value too (in some internal structure) because the add-in doesn’t load. If I remove the HKLM key, all is well.

    I notice other people seem to have this working – so presume I’ve missed a step somewhere? I’d appreciate any pointers on this.

    Many thanks again,

    Mike

  70. Larry says:

    I sure wish you would answer the questions regarding custom actions, Misha.  I program in VB and I’m trying to understand how to use the three C# code segments, but I’m struggling.

    Why not just give us a complete walkthrough for C# or VB and be done with it?  That way we can take our pick.

  71. Nikhil Sharma says:

    Hi,

    Thanks alot Misha.

    This article solved my lots of problems.

    Thanks and Best Regards,

    Nikhil sharma

  72. mailtorakib says:

    Hello Misha,

    Thank you for this nice article.

    I am trying to build an add-in for Outlook 2003 and Outlook 2007. I have applied this method as you described for installing the add-in for all user. It is working for Outlook 2003 and Registry entries propagates as they should for Outlook 2007.

    My add-in loads in Outlook 2003 and works fine but it doesn’t load in Outlook 2007. After checking in the Tools –> Trust Center –> Addins, I found out that my Addin is listed as Inactive addin. I tried the approach for activating inactive addins, but it still doesn’t load. I have tried to grant full trust manually using Caspol.exe again and again, but it doesn’t help.

    The "LoadBehavior" entry in the registry remains 3 even after the addin fails to load.

    Can you please give me any idea on this issue?

    Thanks

    Rakib Hasan

  73. Mike Hatfield says:

    Hi Rakib

    You’re seeing exactly the same problem as in my comment: http://blogs.msdn.com/mshneer/archive/2007/09/05/deploying-your-vsto-add-in-to-all-users-part-ii.aspx#9202273

    What’s happening is Office 2007 sees the HKLM entries and immediately flags your Addin with LoadBehavior=3. There’s nothing I’ve found to workaround this.

    Mike

  74. All, with the help of one of the readers we have confirmed the source of the killbit problem.

    It turns out that some international installations of Windows XP SP2 do install the killbit (I did suspect one of the security updates – but turned out this was way simpler than that). We have confirmed that installing Windows XP SP2 Czech OS do cause killbit to appear, but that is not the case with either US or German editions.Such inconsistency is the source of major problems for out developers where solutions mysteriouly do not work at customers sites.

    We did work with folks in Windows to get this issue addressed by publishing a global update removing this reg key but due to relatively easy workaround, the relatively old age of the OS itself and thus limited support scope – the update did not get approved.

    Instead, Microsoft we are planning to publish a KB article confirming the problem and also recommending to either remove the registry key during the setup or, if no custom setup of the solution is done e.g. when doc-level solution are deployed onto a server, then solution code can detect the presence of this registry key and inform the user that this key needs to be removed for the solution to work properly.

    Thanks a lot to Ernst for helping to troubleshoot this.

    Misha

  75. mailtorakib says:

    Hi Mike,

    Thanks a lot. Mine is the same problem as yours. After removing the HKLM entries it is working fine.

    So, what I understood that, I can’t make the registry entries for both outlook simultaneously. So we must re-install the add-in each time the user switches from one version(2003/2007) of outlook(or any office component) to another.

    Is it right?

    Thanks

    Rakib Hasan

  76. Manpreet says:

    Really Bokus article. NO proper explaination, I went through both part. In second part, When Author is writing about custom action. Not a single proper step given about how and what we have to do.

    I went through from first and came to custom registry action. I stuck because Author is busy to give the credit to his friend, He forgot , he is explaining this article, Even there is no other url given through Which developer can go through and understand how to implement the require step.

    No worth, to get half knowledge. I appriciate if Author share either one sample project code or explain proper step.

    I feel First time , I saw very unprofessional article in this site.

    manpreetsinghbhatia@gmail.com

  77. Manpreet Singh Bhatia says:

    Hi Everyone,

    See more better and more relaible example has given by Microsoft.Url is

    http://msdn.microsoft.com/en-us/library/cc136646.aspx

  78. Manpreet says:

    See this article to understand this article

    http: // msdn.microsoft.com/en-us/library/cc136646.aspx

  79. Wasabi says:

    Thank’s a lot.

    This explains a lot why my LoadBehavior get sets to 0 in HKLM

    Wasabi

  80. Dennise says:

    How can i deploy an outlook add-in to all users using Terminal Server and Citrix.

    Any help would be much appreciated.

    Thanks.

  81. sri.net says:

    Hello Misha

    I am a beginner at this vsto addin

    i just created a combined setup project for individual addins for word, excel and power point

    i also added the setsecurity project for making the assemblies FullTrust

    all the installation, usage and and unistallation is working perfectly

    one problem is that the Security Code group created for the addins is not getting overwritten when i am re-installing or deleting when i am uninstalling

    What should i do???

    thank you again for this post

  82. What do you mean when you state, about 2003 addin not showing up in Outlook COM-Addins list when you say:

    <blockquote>From this point on the loading failures can be seen using

    VSTO_DISPLAYALERTS environment variable.</blockquote>

    I cannot find any information about VSTO_DISPLAYALERTS. Where is this environment variable set and where does one view it?

    advTHANKSance

  83. Oh, it should be VSTO_SUPPRESSDISPLAYALERTS. I will update the post.

  84. Dennise says:

    Hi,

    I hope someone can help me. this is my problem, we have an add-in created in 2003. And then I upgraded it using vb 2005. upgrade the version label. When I upgrade the previous add-in version 1.0 installed on the clients machine to 1.2, it worked fine.

    Now, I have created another upgrade on the add-in. so now I have version 1.3. The problem now is when I upgrade the add-in on client’s machinen from 1.2 to 1.3, the add-in is not being loaded on outlook. It is returning an error, failed to grant permission thing…. And then when i repaired 1.3, it is now working fine.

    Here is another wierd thing, when i try to upgrade the add-in from 1.0 to 1.3 (skipping 1.2), everything is working fine.

    So I am really not sure what is happening when i upgrading the add-in from 1.2 to 1.3 that’s causing the permission issue.

    Can someone please help me. I am kind a desperate in here.

    THanks a lot

    Dennise

  85. Jason Drawmer says:

    Hi,

    I’m just wondering – are those 3 pieces of code (with obviously different content) required in order for this to work – or do they simply clean up the registry at dfferent points in time?

    I’ve been struggling to get the InstallAllUsers to work with Office 2007, and require it for my Outlook add-in and am going to attempt to adopt this approach but first wanted to make sure.

    Also – if they are required, can they simply be added to my Installer class which i’ve used to handle CAS policies?

  86. Arjun KT says:

    Hi,

    I was just trying the code for OutlookWord 2010. But the registry entries were not created for them.

    But for outlook 2007 it worked like a charm.

    Are there any changes i can do ? Or Is this not possible in outlook 2010 ??

    Thanks,

    Arjun

  87. Shammas says:

    Hi Misha,

    I am using VIsual Studio 2013 to create Addin for Outlook 2013. My VSTO itself is creating a registry entry for HKCU. So the user who installed it can use the Addin. Since it is not creating a entry for HKLM , other users cannot see the Addin while the outlook is open in their own profile.

    I tried to create a set up project and created the registry path as below.

    HKLMSoftwareMicrosoftOfficeOutlookAddinsAddin_ID

    But the Windows is creating the entry in the below location.

    HKLMSoftwareWow6432NodeMicrosoftOfficeOutlookAddinsAddin_ID

    Just wondering the VSTO alone can create an entry HKLM like it is creating an entry in HKCU now.

    Your replies will be highly appreciated