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

时间:2014-05-06 06:25:06

标签: .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,并从它在该目录中找到的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是如何做到的。

1 个答案:

答案 0 :(得分:1)

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

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