COM注册失败:“;自动化错误:系统找不到指定的文件";,将dll安装到tlb文件以外的其他文件夹时

COM注册失败:“;自动化错误:系统找不到指定的文件";,将dll安装到tlb文件以外的其他文件夹时,com,wix,registry,dllregistration,heat,Com,Wix,Registry,Dllregistration,Heat,我们在VB.NET中开发了一个COM组件(我们称之为MyLib),供Access应用程序(我们称之为MyApp)使用。为此,我们需要使用生成的MyLib.dll和MyLib.tlb文件进行COM注册。当我将这两个文件安装到MyApp的文件夹中时,一切正常,COM函数被正确调用。然而,当我将dll安装到一个公共文件夹中时,我在标题中提到了一个错误-我这样做的原因是因为我们希望允许在同一台机器上安装不同版本的MyApp。因此,如果COM组件没有更改,我们当然希望在这些不同版本之间共享它,并让Wind

我们在VB.NET中开发了一个COM组件(我们称之为MyLib),供Access应用程序(我们称之为MyApp)使用。为此,我们需要使用生成的MyLib.dll和MyLib.tlb文件进行COM注册。当我将这两个文件安装到MyApp的文件夹中时,一切正常,COM函数被正确调用。然而,当我将dll安装到一个公共文件夹中时,我在标题中提到了一个错误-我这样做的原因是因为我们希望允许在同一台机器上安装不同版本的MyApp。因此,如果COM组件没有更改,我们当然希望在这些不同版本之间共享它,并让Windows进行引用计数

我不确定应该将MyLib.tlb文件放在哪里,或者放在MyApp的安装文件夹中,或者放在与MyLib.dll相同的公用文件夹中。但无论如何,我尝试了两个位置,它们都给出了相同的错误。我试图比较将MyLib.*放入MyApp文件夹时的注册表文件,以及将MyLib.dll放入公用文件夹时的注册表文件。除了我试图在HKCR\Wow6432nodes\CLSID{MYCLSID}\InprocServer32下注册的类的代码库之外,我看不到任何差异。另一件我不明白的事情是,在这两种情况下,HKCR\Wow6432nodes\CLSID{MYCLSID}下都没有名为TypeLib的子键,我认为这是将TypeLib链接到dll的方法(但为什么在我将tlb和dll放在同一文件夹中时,它仍在工作?)因为在MyApp中,它只知道有一个我们通过MyLib.tlb的引用添加的引用

我不太明白COM引用是如何为Access应用程序工作的,所以如果我错了,请纠正我。谁能告诉我我做错了什么?注册共享COM dll的正确方法是什么(是否将dll和tlb同时放入共享文件夹)?谢谢

更新:

关于COM注册,我正在使用WIX创建Windows安装程序,并使用heat.exe从dll和tlb文件中获取信息。生成的文件包括类、ProgID、TypeLib和注册表标记的信息。正如我提到的,从WIX配置的角度来看,我的两种情况之间的唯一区别是我放置MyLib.dll文件的位置(我假设将MyLib.tlb文件放在MyApp安装文件夹中是正确的方式,同样,如果我错了,请纠正我的错误),当我将dll和tlb文件都放在应用程序的安装文件夹中时,它确实有效。下面是注册后的一些注册表结构

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

其次,我有HKLM\Software\Classes\CLSID\{MyCLSID},这个键的结构与上面描述的相同

第三,HKCR \{MYPROGIDs},这些只是我的类的progid

第四,HKCR\Typelib\{LibID},它包含来自tlb文件的信息,该ID来自COM组件项目的程序集GUID

最后,在HKEY_类\u ROOT\Interface\{InterfaceID}中,有一个名为ProxyStubClsid32的子键,其值为{00020424-0000-0000-C000-0000000000 46},还有一个名为TypeLib的子键,其值为my LibID

看起来唯一的区别是第一项中的代码基(我可能是错的,但这就是我所看到的)。如果您发现任何问题,请告诉我。谢谢

第二次更新:

将MyLib.dll安装到共享文件夹后,COM调用失败。但是,如果我将SHARED_FOLDER\MyLib.dll的所有代码基值替换为INSTALLDIR\MyLib.dll,并将MyLib.dll复制到INSTALLDIR,它实际上可以工作。反之亦然,在我将MyLib.dll安装到INSTALLDIR之后(在这种情况下COM正在工作),我将代码基值从INSTALLDIR\MyLib.dll更改为SHARED\u FOLDER\MyLib.dll,并复制到SHARED\u FOLDER,这次失败了。因此,似乎这正是安装位置的问题,这与我对COM的理解相反。我不认为共享_文件夹存在权限问题(我可能错了),因为它位于我的安装程序创建的文件夹中

我不太明白COM引用在Access应用程序中是如何工作的

com对象在windows上的工作方式与1990年出现的相同。因此,我们谈论的是一种已经存在了22年的肉和土豆技术(在.net中创建对象之前很久)

因此,com的工作原理与Access、Delphi、FoxPro、VB6或任何能够使用com对象的系统是一样的

接下来,重要的是要记住,对于此类com对象,计算机上此类对象的注册表本质上是全局的

没有什么比动态链接放置在与.net相同文件夹中的对象更接近的概念了

因此.net的工作方式不需要全局注册(事实上,您不需要任何注册!)

但是,在.net中,如果愿意,可以在全局程序集中注册对象(GAC)。这是您的选择,但这样的选择不是标准的windows com对象,而是.net对象。因此,这些.net对象是零,与我们22年来使用的标准windows com对象无关

因此.net中的大多数对象实际上都是dir的本地对象,但这不是s的选择