使用.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_1\example.dll,将目录更改为 c:\test_1 并运行 regasm.exe /tlb /codebase example.dll。据我所知,这至少做了这些事情:它注册 DLL,创建 TLB (c:\test_1\example.tlb) 并以某种方式注册 TLB 本身(请参见下面我的意思)。
现在,我将 DLL 移至 c:\test_2,将注册和 TLB 生成实用程序放入 c:\test_2,将目录更改为 c:\test_2 并运行我的实用程序。显然,DLL 已正确注册,并且 TLB 已生成。但 TLB 不是挂号的(见下文)。
我现在的问题是如何从 .NET 中注册 TLB。
通过注册 TLB,我的意思是:当使用如上所示的 regasm.exe 时,它显然会将 TLB 的路径放入注册表中(至少,我在那里找到了它)。当您使用 oleview.exe 查看相应的类型库时,它会显示该路径。当我使用自己的实用程序进行注册和 TLB 生成时,该路径不会更新 - 该路径始终是最后运行 regasm.exe 时设置的路径。
这会导致无法找到TLB的情况,例如:将 DLL 和我的实用程序移动到另一个目录并运行该实用程序后,通过 Excel 进行操作。
这是实用程序源代码的相关部分(VB.net、错误处理和用户界面已删除):
sub Register()
Dim s_Path As String
Dim asm_DLL As [Assembly]
Dim rs_DLL As RegistrationServices
Dim tlc_DLL As TypeLibConverter
Dim ns_DLL As cls_TLBCreatorNotifySink
Dim tlb_DLL As UCOMICreateITypeLib
s_Path = Application.StartupPath & "\example.dll"
asm_DLL = Assembly.LoadFrom(s_Path)
rs_DLL = New RegistrationServices()
rs_DLL.RegisterAssembly(asm_DLL, AssemblyRegistrationFlags.SetCodeBase)
s_Path = Application.StartupPath & "\example.tlb"
ns_DLL = New cls_TLBCreatorNotifySink
tlc_DLL = New TypeLibConverter
tlb_DLL = CType(tlc_DLL.ConvertAssemblyToTypeLib(asm_DLL, s_Path, TypeLibExporterFlags.None, ns_DLL), UCOMICreateITypeLib)
tlb_DLL.SaveAllChanges()
end sub
Public Class cls_TLBCreatorNotifySink
Implements ITypeLibExporterNotifySink
Public Sub ReportEvent(eventKind As System.Runtime.InteropServices.ExporterEventKind, eventCode As Integer, eventMsg As String) Implements System.Runtime.InteropServices.ITypeLibExporterNotifySink.ReportEvent
End Sub
Public Function ResolveRef(assembly As System.Reflection.Assembly) As Object Implements System.Runtime.InteropServices.ITypeLibExporterNotifySink.ResolveRef
Return Nothing
End Function
End Class
我希望我能够足够清楚地表达问题。我的问题归结为.NET 中是否有一个合理的方法使我能够在注册表中设置 TLB 的路径,或者我是否必须直接操作注册表中的相应条目(这很愚蠢,因为没有人知道是否下一个 Windows 版本使用相同的条目);一个额外的好处是知道 regasm.exe 是如何做到这一点的。