39

我正在使用以下命令创建一个 COM 对象(来自本机代码)CoCreateInstance

const 
   CLASS_GP2010: TGUID = "{DC55D96D-2D44-4697-9165-25D790DD8593}";

hr = CoCreateInstance(CLASS_GP2010, nil, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IUnknown, out unk);

实际上,我在 Delphi 中,这意味着我调用了辅助函数:

CreateComObject(CLASS_GP2010);

大多数情况下,此功能会成功。但有时,在同一个可执行文件中,在同一个进程中,调用CoCreateInstance失败并显示:

Unspecified error (0x80004005 = E_FAIL)

再次调用该函数可能成功,也可能失败。没有(明显的)押韵或理由。

这不是我的 COM dll

如果这是我编写的普通COM dll,我会开始放入OutputDebugStringDLL_ATTACH当有人尝试调用时DllGetClassObject,我会确认 COM 正确加载了我的 DLL,并且它正确地要求实例化一个类。

不幸的是,它不是 COM dll;这是一个 .NET 程序集 dll。而且 COM 子系统不会简单地 “加载”我的dll. 相反,COM 被指示加载mscoree.dll

HKEY_CLASSES_ROOT
   CLSID
      {DC55D96D-2D44-4697-9165-25D790DD8593}
         InprocServer32
            @default = mscoree.dll

mscoree.dll导出所需的GetClassObject功能。mscoree.dll回来的也是E_FAIL,不是我。在我的开发机器上从未发生过故障,但在客户机器上总是间歇性地失败。

如何启用 .NET 日志记录?

问题是,因为mscoree.dll那个返回E_FAIL(而不是任何有用的东西):我如何让它告诉我问题是什么?

例如,似乎唯一遇到故障的客户(除了是唯一大量使用 COM 对象的客户)碰巧在 Windows XP 上。也许他们遇到了 .NET 框架(版本 4 之前)中的已知错误,您无法将不同版本的 .NET 运行时加载到同一进程中

这样做会引入一个 CLR 版本依赖关系,它可能与宿主进程期望的 CLR 版本冲突

在使用 COM 包装器时,MSDN 上的一篇文章中也提到了这种故障模式;您可以选择指定 a clrVersion

如果已经加载了另一个版本的 CLR,并且可以在进程中并行加载指定的版本,则加载指定的版本;否则,使用加载的 CLR。这可能会导致加载失败。

如果这我在 Windows XP 或 .NET 框架上的早期版本中间歇性加载失败的原因,我该如何mscoree.dll告诉我呢?

如果原因是其他原因,我如何让 .NET 告诉我?

4

2 回答 2

1

您可以使用程序集绑定失败日志记录功能 - 需要启用它,然后您可以使用融合日志查看器查看结果 http://msdn.microsoft.com/en-us/library/e74a18c4(v=vs. 110).aspx 不确定如何将其安装到客户端计算机上。

当我第一次读到这篇文章时,我的第一个想法是在 win xp 机器上似乎最常见的是这是一个 .net 版本/位问题,或者你的 .net dll 是否缺少这些机器上不存在的依赖项。

于 2014-06-29T18:27:14.273 回答
0

至少,如果您要在 Visual Studio 的调试器中运行它,您可能能够捕获第一次机会异常并获得一些洞察力。至少,您想知道 E_FAIL 会导致什么样的错误。即使您没有调试符号,您也应该能够做到这一点。

此外,即使您不能在同一个进程中加载​​多个 .NET VM,通过对 App.config 和 .dll 清单进行一些手动操作,您也可以在同一个 .NET VM 中加载 .dll,即使它们是针对不同的编译器编译的。

最后,检查应用程序事件下的 Windows 事件查看器,看看那里是否记录了任何内容。

于 2013-08-07T23:45:59.257 回答