How to download Excel Addin using Interop

I have AddIn, which I want to call through an Excel connection from a C # winforms application.

I can’t download the addon, etc., if I don’t delete and tar it every time (this apparantly doing something with Excel doesn’t load add-ons when you use interop -btw, you cannot make them work in C #). Unfortunately, this is slow and annoying for the user, so I need to simplify it.

I want to have one instance of Excel, but download the already installed add-on without causing this problem to be installed / reinstalled.

I searched and searched, but everything I found on google gives a solution to install / reinstall. Is there any other way? The add-in is installed, I just want Excel to download it.

This is what I am doing at the moment (taken from google'd advice):

// loop over the add-ins and if you find it uninstall it. foreach (AddIn addIn in excel.AddIns) if (addIn.Name.Contains("My Addin")) addin.Installed = false; // install the addin var addin = excel.AddIns.Add("my_addin.xll", false); addin.Installed = true; 
+6
source share
2 answers

After some time, I found the answer hidden in strange places in MS help : and this is a blog post .

That is not all you need. It should be noted: you must have at least one workbook open or otherwise Excel barfs. Here you need to enter the error code:

 var excel = new Application(); var workbook = excel.workbooks.Add(Type.Missing); excel.RegisterXLL(pathToXll); excel.ShowExcel(); 

If you want, you can close the temporary book (if you ran some macros, etc.) and do not forget to tidy up everything with a lot of calls in Marshal.ReleaseComObject!

+7
source

It seems that you need to get the correct Excel process to work. Use this class to open an Excel document:

  class ExcelInteropService { private const string EXCEL_CLASS_NAME = "EXCEL7"; private const uint DW_OBJECTID = 0xFFFFFFF0; private static Guid rrid = new Guid("{00020400-0000-0000-C000-000000000046}"); public delegate bool EnumChildCallback(int hwnd, ref int lParam); [DllImport("Oleacc.dll")] public static extern int AccessibleObjectFromWindow(int hwnd, uint dwObjectID, byte[] riid, ref Window ptr); [DllImport("User32.dll")] public static extern bool EnumChildWindows(int hWndParent, EnumChildCallback lpEnumFunc, ref int lParam); [DllImport("User32.dll")] public static extern int GetClassName(int hWnd, StringBuilder lpClassName, int nMaxCount); public static Application GetExcelInterop(int? processId = null) { var p = processId.HasValue ? Process.GetProcessById(processId.Value) : Process.Start("excel.exe"); try { Thread.Sleep(5000); return new ExcelInteropService().SearchExcelInterop(p); } catch (Exception) { Debug.Assert(p != null, "p != null"); return GetExcelInterop(p.Id); } } private bool EnumChildFunc(int hwndChild, ref int lParam) { var buf = new StringBuilder(128); GetClassName(hwndChild, buf, 128); if (buf.ToString() == EXCEL_CLASS_NAME) { lParam = hwndChild; return false; } return true; } private Application SearchExcelInterop(Process p) { Window ptr = null; int hwnd = 0; int hWndParent = (int)p.MainWindowHandle; if (hWndParent == 0) throw new Exception(); EnumChildWindows(hWndParent, EnumChildFunc, ref hwnd); if (hwnd == 0) throw new Exception(); int hr = AccessibleObjectFromWindow(hwnd, DW_OBJECTID, rrid.ToByteArray(), ref ptr); if (hr < 0) throw new Exception(); return ptr.Application; } } 

Use the class in your application as follows:

 static void Main(string[] args) { Microsoft.Office.Interop.Excel.Application oExcel = ExcelInteropService.GetExcelInterop(); foreach (AddIn addIn in oExcel.AddIns) { addIn.Installed = true; } } 
0
source