我正在使用COM shim向导开发Word共享加载项。 http://blogs.msdn.com/b/mshneer/archive/2010/03/19/com-shim-wizards-for-vs-2010.aspx
在我尝试使用某些线程之前,一切正常。 在主线程中创建的COM对象的TYPE_E_LIBNOTREGISTERED异常的某些机器上失败。
我有来自某个Word事件的Word文档对象(_doc)并尝试使用来自这样的STA线程:
Word.Document _doc;
void Start()
{
_mainLoopThread = new Thread(MainLoop);
_mainLoopThread.SetApartmentState(ApartmentState.STA);
_mainLoopThread.IsBackground = true;
_mainLoopThread.Start();
}
void MainLoop()
{
// some code...
Word.Range r = _doc.StoryRanges[Word.WdStoryType.wdMainTextStory];
// some code...
}
我的开发机器,测试机器和大多数用户都可以正常工作。但是对于某些用户,它会失败并出现异常 无法将“Microsoft.Office.Interop.Word.DocumentClass”类型的COM对象强制转换为接口类型“Microsoft.Office.Interop.Word._Document”。此操作失败,因为对于具有IID“{0002096B-0000-0000-C000-000000000046}”的接口的COM组件的QueryInterface调用由于以下错误而失败:库未注册。 (HRESULT的例外情况:0x8002801D(TYPE_E_LIBNOTREGISTERED))。
我们能够重现它的唯一方法 - 安装Office 2013,然后将其删除并安装Office 2007.我检查了注册表,但未发现此guid的任何注册问题。我尝试了MS的工具,应该清除Office 2013中的剩余物, http://support.microsoft.com/kb/2739501 但它没有帮助。
这不是注册问题,因为我可以从主线程使用相同的_doc对象而没有任何错误。 在用于COM-shim的rgs文件中,我使用STA模型 InprocServer32 = s'%MODULE%' { val ThreadingModel = s'Apartment' } 我还在属性链接器高级中将CLR模式设置为STA,但这没有帮助。
我尝试使用CoMarshalInterThreadInterfaceInStream,如此处所示 Cannot call COM object created from STAThread from oher STA threads 但即使在我的开发机器上也无法工作。 这是代码: [的DllImport( “OLE32.DLL”)] static extern int CoMarshalInterThreadInterfaceInStream([In] ref Guid riid,[MarshalAs(UnmanagedType.IUnknown)] object pUnk,out IStream ppStm);
IStream _docForThreadStream = null;
Guid _docInterfaceGuid;
void InitDocForThread()
{
object[] attr = _doc.GetType().GetCustomAttributes(typeof(GuidAttribute), false);
GuidAttribute g = (GuidAttribute)attr[0];
_docInterfaceGuid = new Guid(g.Value);
CoMarshalInterThreadInterfaceInStream(ref _docInterfaceGuid, Marshal.GetIUnknownForObject(_doc), out _docForThreadStream);
}
[DllImport("ole32.dll")]
static extern int CoGetInterfaceAndReleaseStream(IStream pStm, [In] ref Guid riid, out object ppv);
Word.Document _docForThread = null;
void MainLoop()
{
object pDoc;
int hr = CoGetInterfaceAndReleaseStream(_docForThreadStream, ref _docInterfaceGuid, out pDoc);
// _docForThreadStream != null, hr == E_NOINTERFACE
}
当我尝试从IStream获取对象时,CoGetInterfaceAndReleaseStream给了我E_NOINTERFACE。任何人都可以发给我链接C#的工作示例吗?我用谷歌搜索,但只找到了一些C ++的例子。
Office COM注册看起来像这样一种方式,它适用于同一个线程(在与办公室相同的线程中运行的加载项),但无法编组到另一个STA线程......
答案 0 :(得分:-1)
就在最近,我们观察了同样的情况:TYPE_E_LIBNOTREGISTERED在线程中调用Word对象模型时。您必须仅在主线程中使用任何Office对象模型。请在http://www.add-in-express.com/creating-addins-blog/2010/11/04/threads-managed-office-extensions/找到一些信息和更多链接。