如何使用Interop加载Excel Addin

我有一个AddIn,我想从C#winforms应用程序通过Excel互操作调用。

我不能得到加载等加载,除非我每次卸载和树脂安装(这是在Excel中使用互操作时无法加载插件,无法让他们的例子在C#中工作)。 不幸的是,这对用户来说太慢而烦人,所以我需要简化它。

我想有一个Excel的实例,但加载已经安装的插件,而不强制这个安装/重新安装问题。

我search和search,但我发现在谷歌上提供的解决scheme,安装/重新安装。 有没有其他的方法? 加载项已安装,我只是想要加载它。

这是我现在正在做的(从google'dbuild议中获取):

// 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; 

过了一会儿,我发现答案隐藏在MS帮助中的奇怪的地方: 这篇博文 。

这不是所有你需要的信息。 注意事项:您必须至less有一个工作簿打开或否则Excel的barfs。 这里有一些粗鲁的代码开始:

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

如果你想要的话,你可以closures临时工作簿(如果你已经运行了一些macros等),记得用大量的Marshal.ReleaseComObject来调用一切。

看来,你必须得到正确的Excel过程来处理。 使用这个类打开Excel文档:

  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; } } 

在你的应用程序中使用这样的类:

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