I have an excel addin class that has this function:
public void testRibbon()
{
Excel.Workbook workbook = this.Application.ActiveWorkbook;
Excel.Worksheet activeSheet = workbook.Sheets[1];
Excel.Range range = activeSheet.get_Range(JOB_ID_FIELD + HEADER_ROW, TOTAL_STATUS_PERCENTAGE_KEY_FIELD + (10 + 1).ToString());
range.get_Range("C4").Value = "test Ribbon complete";
}
In the ribbon I added a button that when pressed will call testRibbon in a thread:
private void process_Click(object sender, RibbonControlEventArgs e)
{
Thread processThread = new Thread(delegate(){
Globals.ExcelAddin.testRibbon();
});
processThread.Start();
}
This causes a cast error:
Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Office.Interop.Excel._Workbook'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{000208DA-0000-0000-C000-000000000046}' failed due to the following error: Error loading type library/DLL. (Exception from HRESULT: 0x80029C4A (TYPE_E_CANTLOADLIBRARY)).
The cast error doesn't happen if I don't use a new thread.
Edit:Tried using task factory, same error:
var task2 = Task.Factory.StartNew(
() =>
{
Globals.BobStats.testRibbon();
});
Using multiple threads in Excel makes no sense because Excel's COM interface is basically single threaded (see this article). There might be further restrictions from within an add-in.
Yet I have to say I don't really understand what the error message is trying to say.
I think at the moment, you are being connected by COMObject to interface type 'Workbook'... it will automatically create a new unmanaged thread and that will crash with your thread when you Start(). To specifically, when you create thread object it will save some data structures to shared memory and did not use Start() so thread was not executing at this time
When you use an Excel interface method from a worker thread then the method call needs to be marshaled. In other words, the call needs to be made from the thread that created the Application object. Same idea as using Control.Invoke() or Dispatcher.Invoke() in a .NET gui app.
To make that work, COM needs to know what the arguments are for the method so it can copy them properly. That is the kind of info that requires the equivalent of Reflection in .NET. Which requires metadata, the metadata that describes a COM method is stored in a type library. The type library for Excel is stored in Excel.exe as a resource.
Finding the type library is what is going wrong here. This info is stored in the registry and it is damaged on your machine for some reason. The most likely key that got whacked is HKLM\SOFTWARE\Classes\TypeLib\{00020813-0000-0000-C000-000000000046}\1.7\0\win32
albeit that it depends on the exact version of Office. You can get more insight from SysInternals' ProcMon utility, you'll see your program searching for the key.
This kind of mishap is rarely limited to just one key. You'll need to get your machine healthy again and reinstall Office.
Oh, and keep in mind that the code doesn't actually run on the worker thread. That requires creating the Application object on that worker thread and calling SetApartmentState() to make it STA before you start it.
User contributions licensed under CC BY-SA 3.0