如何从.NET中以编程方式注册(设置正确的路径)类型库?

如何从.NET中以编程方式注册(设置正确的路径)类型库?,.net,dll,com,registration,typelib,.net,Dll,Com,Registration,Typelib,使用.NET 4.0,我创建了一个启用COM的DLL(我们称之为example.DLL),我注册了它,并使用regasm.exe(regasm.exe/tlb/codebase example.DLL)生成了相应的类型库;类型库称为example.tlb。该程序集具有强名称 到目前为止,这是可行的,我可以在VBA中使用DLL和TLB 但由于某些原因,我需要制作自己的实用程序,用于DLL注册和TLB生成。基本上,此实用程序将与DLL位于同一目录中,并应注册在该目录中找到的DLL,以及从在该目录中找

使用.NET 4.0,我创建了一个启用COM的DLL(我们称之为example.DLL),我注册了它,并使用regasm.exe(regasm.exe/tlb/codebase example.DLL)生成了相应的类型库;类型库称为example.tlb。该程序集具有强名称

到目前为止,这是可行的,我可以在VBA中使用DLL和TLB

但由于某些原因,我需要制作自己的实用程序,用于DLL注册和TLB生成。基本上,此实用程序将与DLL位于同一目录中,并应注册在该目录中找到的DLL,以及从在该目录中找到的DLL生成TLB文件

DLL注册和TLB生成似乎是可行的,但存在以下问题:我还没有找到任何可接受的方法来从.NET 4.0中设置TLB文件的正确路径,因此我非常感谢您的帮助

为了再现和说明,请想象以下情况:

  • 我有c:\test\u 1\example.dll,将目录更改为c:\test\u 1并运行regasm.exe/tlb/codebase example.dll。据我所知,这至少可以做到以下几点:它注册DLL,创建TLB(c:\test\u 1\example.TLB),并以某种方式注册TLB本身(请参见下面我的意思)

  • 现在,我将DLL移动到c:\test\u 2,将我的注册和TLB生成实用程序放入c:\test\u 2,将目录更改为c:\test\u 2并运行我的实用程序。显然,DLL得到了正确注册,并且生成了TLB。但TLB未注册(见下文)

我现在的问题是如何从.NET中注册TLB

通过注册TLB,我的意思是:当使用如上所示的regasm.exe时,它显然会将TLB的路径放入注册表(至少我在注册表中找到了它)。使用oleview.exe查看相应的类型库时,会显示该路径。当我使用自己的实用程序进行注册和TLB生成时,此路径不会更新-该路径始终是上次运行regasm.exe时设置的路径

这会导致TLB无法找到的情况,例如,在将DLL和my utility移动到另一个目录并运行该实用程序后,Excel无法找到TLB

这是实用程序源代码(VB.net、错误处理和用户界面)的相关部分:

我希望我能把这个问题表达得足够清楚。我的问题归结为.NET中是否有一个合理的方法,使我能够在注册表中设置TLB的路径,或者我是否必须直接操作注册表中的相应条目(这将是愚蠢的,因为没有人知道下一个windows版本是否使用相同的条目);另外一个好处是知道regasm.exe是如何实现的。

您应该使用
ConvertAssemblyToTypeLib
的结果进行调用,如下所示:

RegisterTypeLib(tlc_DLL.ConvertAssemblyToTypeLib(asm_DLL, s_Path, TypeLibExporterFlags.None, Nothing), s_Path, Nothing)

<DllImport("oleaut32.dll")> _
Private Shared Function RegisterTypeLib(<MarshalAs(UnmanagedType.Interface)> ByVal ptlib As Object, <MarshalAs(UnmanagedType.LPWStr)> ByVal szFullPath As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal szHelpDir As String) As Integer
End Function
RegisterTypeLib(tlc_DLL.convertsemblyToTypelib(asm_DLL,s_路径,TypeLibExporterFlags.None,Nothing),s_路径,Nothing)
_
私有共享函数寄存器TypeLib(ByVal ptlib作为对象,ByVal szFullPath作为字符串,ByVal szHelpDir作为字符串)作为整数
端函数

Simon,非常感谢。这在原则上是可行的,因此对我来说是一个答案,但请看下面的评论。Simon,一个问题:ConvertAssemblyToTypeLib不接受任何内容作为其最后一个参数(解决这个问题很容易,一定是您这边的输入错误)。Simon,似乎注册的TLB是64位或32位;第一个不能在Excel 32位内使用,后一个不能在Excel 64位内使用。但我必须支持他们两个。最简单的方法是什么?对于那些感兴趣的人来说:RegisterTypeLib在这样使用时不会抛出异常,因此应该测试其返回值,并进行适当的“手动”错误处理。关于最后一个参数,它取决于您的代码,我的代码只是一个示例。关于32对64,您可能需要两次调用该方法:如果您希望同时支持32b进程和64b进程,则需要从32b进程和64b进程调用该方法。请参见本文:这篇Microsoft文章似乎是上面代码的参考:这里的关键遗漏是完全从MS文章中实现UComicCreateTypeLib接口(如果您使用的是C#而不是VB.NET)并调用SaveAllChanges函数。
RegisterTypeLib(tlc_DLL.ConvertAssemblyToTypeLib(asm_DLL, s_Path, TypeLibExporterFlags.None, Nothing), s_Path, Nothing)

<DllImport("oleaut32.dll")> _
Private Shared Function RegisterTypeLib(<MarshalAs(UnmanagedType.Interface)> ByVal ptlib As Object, <MarshalAs(UnmanagedType.LPWStr)> ByVal szFullPath As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal szHelpDir As String) As Integer
End Function