0

我正在使用热量来收集 COM dll 和 tlb 文件(我们称它们为 MyLib.*,在 VB.NET 中开发)来进行 COM 注册。当我将 MyLib.dll 和 MyLib.tlb 安装到应用程序的安装文件夹(即 INSTALLDIR)中时,一切正常。但是,由于我们想让我们的软件的不同版本可以安装在同一台机器上,并且如果他们使用相同版本的 COM 组件,那么只有一个 dll 副本(我认为我们的每个版本的 SW 应该有自己的tlb,如果我错了,请纠正我)应该安装,我们现在想将 MyLib.dll 安装到另一个文件夹中,特别是 PROGRAM_FILES\Common Files\SHARED_FOLDER_NAME,所以现在如果我们的一个版本的软件被卸载,MyLib.dll 将不会被删除,仍然可以被其他版本使用。

但是问题来了:在我将此dll安装到另一个文件夹后,我的COM注册根本无法工作,并且它一直说在我调用COM函数时找不到指定的文件,这表明注册失败。在 WIX 安装程序项目中,除了 MyLib.dll 的这个文件夹之外,一切都相同。

这是安装后的注册表结构:

首先我有 HKCR\CLSID{MYCLSIDs},它们中的每一个都代表我的一个 COM 类。在名为“InprocServer32”的子项中,我有 Assembly、Class、CodeBase、RuntimeVersion、threadingModel。CodeBase要么是普通文件夹(不工作)要么是MyApp的安装文件夹(工作),这是我放置dll的不同位置。我认为 {MYCLSIDs} 下会有另一个子键 TypeLib,因为 Access 只看到 TypeLib,我认为应该有一些从 TypeLib 到实际 dll 的链接,但是,在这两种情况下,这个子键都丢失了,但在第二种情况它仍然有效。它有问题吗?

其次我有 HKLM\Software\Classes\CLSID{MYCLSIDs},这些键的结构当然和上面描述的一样。

第三,HKCR{MYPROGIDs},这些只是我班级的 ProgID

第四,HKCR\Typelib{LibID},包含来自tlb文件的信息,这个ID来自COM组件项目的Assembly GUID。

最后是 HKEY_CLASSES_ROOT\Interface{InterfaceID},有一个名为 ProxyStubClsid32 的子键,其值为 {00020424-0000-0000-C000-000000000046},一个名为 TypeLib 的子键,其值为我的 LibID。

正如我所提到的,唯一的区别是 CodeBase,它存储了 MyLib.dll 所在的位置。为了验证这一点,我做了两个测试:将 MyLib.dll 安装到共享文件夹后,COM 调用失败。但是,如果我将 SHARED_FOLDER\MyLib.dll 的所有 CodeBase 值替换为 INSTALLDIR\MyLib.dll,并将 MyLib.dll 复制到 INSTALLDIR,它实际上可以工作。反之亦然,在我将 MyLib.dll 安装到 INSTALLDIR 后(在这种情况下 COM 正在工作),我将 CodeBase 值从 INSTALLDIR\MyLib.dll 更改为 SHARED_FOLDER\MyLib.dll,并复制到 SHARED_FOLDER,这次它失败了。所以看来,正是安装位置的问题,和我对COM的理解相反。而且我认为 SHARED_FOLDER 没有权限问题(我可能是错的),因为它位于我的安装程序创建的文件夹中。

请帮忙,谢谢!

4

1 回答 1

0

原来,MyLib.dll 正在使用一些其他的库,这些库仍然安装在 MyApp 安装文件夹中。因此,如果 MyLib.dll 安装在共享文件夹中,它会尝试在相同的库中查找这些库,这当然会失败。当我也将这些库安装在共享文件夹中时,它正在工作。

顺便说一句,我发现 fulogvw.exe 在跟踪程序集加载问题时非常有用。例如,在我的失败日志中,它说无法在 SHARED_FOLDER 中加载文件 xxx.dll,xxx.dll 是 MyLib.dll 正在使用的某个库,我不知道 MyLib.dll 需要它,直到我看到日志。

于 2012-07-30T12:11:07.713 回答