Uninstall an Excel Add-In which was previously installed by adxregistrator

Add-in Express™ Support Service
That's what is more important than anything else

Uninstall an Excel Add-In which was previously installed by adxregistrator
Helps functions for modifying the registry 
dirkln




Posts: 73
Joined: 2017-10-05
Hello
I want to programmatically remove an Excel Add-In.
I know Excel has an API using ExcelApplication.AddIns and AddIns2 where I can deactivate an Excel Add-In by using Installed and Open properties on a specific add-in.
But the add-ins is still in the list of available add-ins in the Excel Add-In Manager.
Do you have an API to remove the Add-In entirely from Excel?
I tested this approach:
- remove registry Software\Microsoft\office\16.0\Excel\Options\OPEN<N>=/R <path to add-in>
- remove registry Software\Microsoft\office\16.0\Excel\Add-in Manager\<path to add-in>
- remove registry Software\Microsoft\office\16.0\Excel\AddInLoadTimes\<path to add-in>
Is there a preferred way to remove an add-in entirely?
The API should encapsulate the version of Excel and work for Excel 2010, 2013 and 2016.
Using a MIS Setup or other external programs is not an option. It has to be done by a loaded COM Add-in.
best regards
Posted 24 Apr, 2019 06:03:26 Top
Dmitry Kostochko


Add-in Express team


Posts: 2875
Joined: 2004-04-05
Hello Dirk,

Do you have an API to remove the Add-In entirely from Excel?


Sorry, we don't have such an API and Microsoft Office does not provide such.

Is there a preferred way to remove an add-in entirely?


As far as I understand, you are installing your add-in by using an MSI installation package, correct? In this case the only right way to "remove" the add-in is to uninstall it when the host application (Excel in your case) is closed.
Posted 24 Apr, 2019 06:42:05 Top
dirkln




Posts: 73
Joined: 2017-10-05
But as far as I understand you are registering the a ADXXLLModule in exactly that way using the adxregistrator?
Here is a log output from Adxregistrator:
17:19:06 1132 The '/R "C:\Dev\install\adxloader.<ouraddinname>.dll"' registry value was created successfully for the 'OURXLLModule' class. I assume you are creating the OPEN<N> key in the registry for the installed version of Excel.

That means you have that code.
Is this code only inside the adxregistrator or is it available in any of the ADX Libraries?
Posted 25 Apr, 2019 02:43:14 Top
Andrei Smolin


Add-in Express team


Posts: 18821
Joined: 2006-05-11
Hello Dirk,

In what way you register the XLL add-in? If you used adxregistrator to register it, you should use adxregistrator to unregister it *correctly*. I assume your COM add-in can start adxregistrator.

Two more points.

XLL may not be ready to being unregistered on the fly. You need to turn it off by the moment you start adxregistrator. Use Excel.AddIns and Excel.AddIns2 collections to get the XLL add-in and turn it off. Introduce a delay between turning the add-in off and starting adxregistrator; see section Wait a Little at https://www.add-in-express.com/docs/net-office-tips.php#wait-a-little.

There's no guarantee that your XLL add-in disappears from the UI after you turn it off and unregister. Restarting Excel guarantees this.


Andrei Smolin
Add-in Express Team Leader
Posted 25 Apr, 2019 06:19:16 Top
fintools




Posts: 8
Joined: 2016-03-24
I wasn't aware of the Excel.AddIns collections, and I'm also in a situation in Excel where the Add-In that is registered by adxregistrator checks, during AddinModule_AddinStartupComplete, for the OPEN(and additional numbers if there are multiple Excel Add-Ins) string value pointing to my XLL. If it doesn't exist, it creates one, and shows a message box to restart Excel.

This works whether the user has Excel set to open to the gallery, or to a new workbook. However I'm not sure where to put the code to remove the XLL when the user is uninstalling the product. I've put the code below in case my description is confusing, and the method I wish to run before the unregistration is XLLUnRegister. There is a 64 and 32 bit XLL, depending on the bitness of Excel.

  private void AddinModule_AddinStartupComplete(object sender, EventArgs e)
        {
            //Check to make sure there is a valid path to the user's license file
            CheckForRegistrationKey();

            //Check to see if XLL is registered
            XLLRegistration(Path);
        }


        public static void XLLRegistration(string path)
        {
            try
            {
                string versionName = CurrentInstance.ExcelApp.Version;
                int length = versionName.IndexOf('.');
                versionName = versionName.Substring(0, length);
                
                // int.parse needs to be done using US Culture.
                int versionNumber = int.Parse(versionName, System.Globalization.CultureInfo.GetCultureInfo("en-US"));

                if (versionNumber < 12)
                {
                    MessageBox.Show("FinTools NET Does not support versions of Excel older than 2007",
                        "Compatibility Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                string addInPathBefore = "Software\Microsoft\Office\" + versionNumber.ToString() + ".0\";
                string optionsKey = "Excel\Options";
                string eightySixXLL = "FinToolsx86.xll";
                string sixtyFourXLL = "FinToolsx64.xll";
                string xllPath = "";
                string xllEntry = "";
                string xllName="";

                //Check bitness of Excel to find which XLL to use
                if (IntPtr.Size == 4) //x86
                {
                    //From here on out, assume Windows is 64 bit, and put in Program Files, regardless of Excel bitness
                    xllEntry = "/R "" + path + "Bin\" + eightySixXLL + """;
                    xllPath = path + "Bin\" + eightySixXLL;
                    xllName = eightySixXLL;
                }
                else
                {

                    xllPath = path + "Bin\" + sixtyFourXLL;
                    xllEntry = "/R "" + path + "Bin\" + sixtyFourXLL + """;
                    xllName = sixtyFourXLL;
                }
                
                if(xllPath.Length==0)
                        MessageBox.Show("FinTools NET is not properly installed, please contact MITI support", "Error loading XLL", MessageBoxButtons.OK, MessageBoxIcon.Error);

                //XLL is registered and opening correctly
                string optionKey = OptionsExists(addInPathBefore + optionsKey, xllName);
                if (optionKey.Length > 1) return;

                //Check if Excel bitness has changed
                if (IntPtr.Size == 4) //x86
                {
                    optionKey = OptionsExists(addInPathBefore + optionsKey, sixtyFourXLL);
                    if (optionKey.Length > 0)
                        MessageBox.Show("Excel has changed from 64 bit to 32 bit, please reinstall FinTools NET", "Error loading XLL", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    optionKey = OptionsExists(addInPathBefore + optionsKey, eightySixXLL);
                    if (optionKey.Length > 0)
                        MessageBox.Show("Excel has changed from 32 bit to 64 bit, please reinstall FinTools NET", "Error loading XLL", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                //Register XLL
                if (RegisterXLL(addInPathBefore + optionsKey, xllEntry))
                {
                    MessageBox.Show("FinTools NET has been updated, please restart Excel", "FinTools NET", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                MessageBox.Show("FinTools NET is not properly installed, please contact MITI support", "Error loading XLL", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Error loading XLL", MessageBoxButtons.OK, MessageBoxIcon.Error);
                
            }
        } 


        //This needs to remove the XLL
        public static void XLLUnRegister(string path)
        {
            try
            {
                string versionName = CurrentInstance.ExcelApp.Version;
                int length = versionName.IndexOf('.');
                versionName = versionName.Substring(0, length);

                // int.parse needs to be done using US Culture.
                int versionNumber = int.Parse(versionName, System.Globalization.CultureInfo.GetCultureInfo("en-US"));

                string addInPathBefore = "Software\Microsoft\Office\" + versionNumber.ToString() + ".0\";
                string managerKey = "Excel\Add-in Manager";
                string optionsKey = "Excel\Options";
                string eightySixXLL = "FinToolsx86.xll";
                string sixtyFourXLL = "FinToolsx64.xll";
                string xllPath = "";
                string xllName;

                //Check bitness of Excel to find which XLL to use
                if (IntPtr.Size == 4) //x86
                {
                    if (path.Length > 0)
                        xllPath = "/R "" + path + "Bin\" + eightySixXLL + """;
                    xllName = eightySixXLL;
                }
                else
                {
                    if (path.Length > 0)
                        xllPath = "/R "" + path + "Bin\" + sixtyFourXLL + """;
                    xllName = sixtyFourXLL;
                }

                if (xllPath.Length == 0) return;
                   

                //XLL is registered and opening correctly

                if(DeleteOption(addInPathBefore + optionsKey, xllName)) return;

                //XLL is registered but unchecked
                if(DeleteAddInManager(addInPathBefore + managerKey, xllPath)) return;

                return;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Error Unregistering XLL", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }
        }

Posted 03 May, 2019 14:43:11 Top
Andrei Smolin


Add-in Express team


Posts: 18821
Joined: 2006-05-11
Hello Dirk,

Sorry for the delayed response; we had a mixture of week end and holidays.

fintools writes:
However I'm not sure where to put the code to remove the XLL when the user is uninstalling the product


If you use adxregistrator.exe to undergister your COM add-in, you can invoke XLLUnRegister in the OnUnregister event of the add-in module. Note that specifying an event handler of that event causes adxregistrator to start an Excel application via Automation, create an instance of your add-in module and raise that event.


Andrei Smolin
Add-in Express Team Leader
Posted 08 May, 2019 07:08:08 Top
fintools




Posts: 8
Joined: 2016-03-24
Thank you Andrei. I've created that event, but I'm still getting an Object Required error on the below code. I believe it's because I'm not sure of how to create an instance of the Add-In module. Thanks

  private void AddinModule_OnUnregister(object sender, EventArgs e)
        {
            XLLUnRegister(Path);
        }


        public static void XLLUnRegister(string path)
        {
            try
            {
                string versionName = CurrentInstance.ExcelApp.Version;
                MessageBox.Show(versionName, "test", MessageBoxButtons.OK, MessageBoxIcon.Error);
                int length = versionName.IndexOf('.');
                versionName = versionName.Substring(0, length);

                // int.parse needs to be done using US Culture.
                int versionNumber = int.Parse(versionName, System.Globalization.CultureInfo.GetCultureInfo("en-US"));

                string addInPathBefore = "Software\Microsoft\Office\" + versionNumber.ToString() + ".0\";
                string managerKey = "Excel\Add-in Manager";
                string optionsKey = "Excel\Options";
                string eightySixXLL = "FinToolsx86.xll";
                string sixtyFourXLL = "FinToolsx64.xll";
                string xllPath = "";
                string xllName;

                //Check bitness of Excel to find which XLL to use
                if (IntPtr.Size == 4) //x86
                {
                    if (path.Length > 0)
                        xllPath = "/R "" + path + "Bin\" + eightySixXLL + """;
                    xllName = eightySixXLL;
                }
                else
                {
                    if (path.Length > 0)
                        xllPath = "/R "" + path + "Bin\" + sixtyFourXLL + """;
                    xllName = sixtyFourXLL;
                }

                if (xllPath.Length == 0) return;
                   

                //XLL is registered and opening correctly

                if(DeleteOption(addInPathBefore + optionsKey, xllName)) return;

                //XLL is registered but unchecked
                if(DeleteAddInManager(addInPathBefore + managerKey, xllPath)) return;

                return;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Error Unregistering XLL", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }
        }
Posted 13 May, 2019 14:55:42 Top
Andrei Smolin


Add-in Express team


Posts: 18821
Joined: 2006-05-11
Hello Dirk,

This looks like a programming error; you should debug your code.

fintools writes:
I'm not sure of how to create an instance of the Add-In module


An instance of the add-in module is already created: AddinModule_OnUnregister() is executed within that instance.

fintools writes:
CurrentInstance.ExcelApp.Version


Does CurrentInstance returns an instance of the add-in module?


Andrei Smolin
Add-in Express Team Leader
Posted 14 May, 2019 05:29:23 Top
fintools




Posts: 8
Joined: 2016-03-24
Thank you, how would I debug the Unregister? I'm currently using the right click menu on the VS Project to launch the Unregister method.

Not placing this code in a try-catch block gave me more info on the exception. I'm not accessing the ExcelApp property of the AddInModule properly.


        private void AddinModule_OnUnregister(object sender, EventArgs e)
        {
            AddinModule modExcel = new AddinModule();

            string versionName = modExcel.ExcelApp.Version.ToString();
            int length = versionName.IndexOf('.');
            versionName = versionName.Substring(0, length);
            int versionNumber = int.Parse(versionName, System.Globalization.CultureInfo.GetCultureInfo("en-US"));

            XLLUnRegister(Path,versionNumber);
        }


Detailed technical information follows:
---
(Inner Exception)
Date and Time: 5/14/2019 2:45:44 PM
Machine Name: DAVID-SURFACEPR
IP Address: fe80::e0b1:7a77:420b:6e61%14
Current User: DAVID-SURFACEPR\David

Application Domain: taskAppDomain (out-of-proc)
Assembly Codebase: file:///D:/GitHub/FinToolsXLAddin/COMUI/bin/Debug/FinToolsNET.dll
Assembly Full Name: FinToolsNET, Version=2.19.1205.0, Culture=neutral, PublicKeyToken=null
Assembly Version: 2.19.1205.0

Exception Source: FinToolsNET
Exception Type: System.NullReferenceException
Exception Message: Object reference not set to an instance of an object.
Exception Target Site: AddinModule_OnUnregister

---- Stack Trace ----
FinToolsNET.AddinModule.AddinModule_OnUnregister(sender As Object, e As EventArgs)
AddinModule.cs: line 0941, col 13, IL 0013 (0xD)
AddinExpress.MSO.ADXAddinModule.ADXUnregister(t As Type)
FinToolsNET.dll: N 0617 (0x269) IL



(Outer Exception)
Date and Time: 5/14/2019 2:45:44 PM
Machine Name: DAVID-SURFACEPR
IP Address: fe80::e0b1:7a77:420b:6e61%14
Current User: DAVID-SURFACEPR\David

Application Domain: taskAppDomain (out-of-proc)
Assembly Codebase: file:///C:/WINDOWS/assembly/GAC_MSIL/AddinExpress.MSO.2005/9.2.4635.0__4416dd98f0861965/AddinExpress.MSO.2005.dll
Assembly Full Name: AddinExpress.MSO.2005, Version=9.2.4635.0, Culture=neutral, PublicKeyToken=4416dd98f0861965
Assembly Version: 9.2.4635.0

Exception Source:
Exception Type: AddinExpress.MSO.ADXExternalException
Exception Message: An error has occurred in the code of the add-in.

---- Stack Trace ----
Posted 14 May, 2019 13:55:26 Top
Andrei Smolin


Add-in Express team


Posts: 18821
Joined: 2006-05-11
Hello Dirk,

You can add a number of debug messages to your code; use System.Diagnostics.Debug.WriteLine(). If the add-in is built in the Debug configuration, you collect the messages at run time using DebugView (see http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx).

fintools writes:
AddinModule modExcel = new AddinModule();


Although you can create a new add-in module instance, it won't be connected to Office. You should use the module in which the AddinModule_OnUnregister method is run: this.ExcelApp.Version.ToString().


Andrei Smolin
Add-in Express Team Leader
Posted 15 May, 2019 04:29:23 Top