如何从非托管 COM dll 生成类型库
Posted
技术标签:
【中文标题】如何从非托管 COM dll 生成类型库【英文标题】:How to generate type library from unmanaged COM dll 【发布时间】:2011-06-26 18:40:37 【问题描述】:我必须在我的 .NET 应用程序中使用第三方非托管 COM dll。我需要修改此程序集以生成custom RCW。为了Edit Interop Assembly,我需要特定程序集的类型库。谁能解释一下?
regsvr32中没有生成类型库的选项。
谢谢, 最好的祝福, 机器人。
【问题讨论】:
【参考方案1】:您需要OLE-COM Object Viewer,它是最新Windows SDK 的一部分。然后您可以转到 File->View Type Lib 并将 IDL 保存到文本文件中。然后,您可以使用MIDL(也是 Windows SDK 的一部分)重新生成 TLB 和头文件。对于基本情况,应该这样做:
midl /out c:\temp /header MyHeader.h MyIDLFile.idl
【讨论】:
嗨,Guido 非常感谢。但我收到以下错误。我会用谷歌搜索它并将其缩短。 [.\Sample.IDL(60):error MIDL2025:syntax error : Expecting a type specification near "single"]【参考方案2】:如果您只想从本机 dll 创建一个互操作程序集(并且本机 DLL 将 TLB 作为资源嵌入),您可以直接在 dll 上调用 tlbimp:
tlbimp Foo.dll /out:Interop.Foo.dll
这将生成 Interop.Foo.dll。然后可以使用 ildasm 来修改 IL:
ildasm Interop.Foo.dll /out=Foo.il
【讨论】:
实际上我认为 tlbimp 需要 Foo.tlb 来生成 Interop.Foo.dll,正如 linkEdit Interop Assembly 中所解释的那样。感谢您的提示【参考方案3】:如果你只有那个 COM DLL,你就不能生成类型库。类型库描述了实现的 COM 接口。但非托管 COM DLL 只需要公开DllGetClassObject
。这只会给你一个IClassFactory
,如果你事先知道正确的类型,它可以让你创建新对象。
【讨论】:
类型库可以在DLL资源中,然后可以被OleView查看并重构。 @sharptooth:确实在某些情况下您已经嵌入了类型库。但是这个问题没有任何意义。 Tlbimp.exe可以解析DLL中的typelibs(使用inputDLL\1
指定资源号)【参考方案4】:
如果 typelib 嵌入在 DLL 资源中并且 TLB 文件本身是必需的,那么第 3 方软件可以提取它(尽管正如其他人指出的那样,这可能不是最理想的选择)。
例如使用Resource Hacker:
-
打开 DLL 文件。
导航到树视图中的 TYPELIB\1\1033(或其他)节点。
从菜单中选择操作 -> 将资源另存为二进制文件...
选择一个文件名并为其指定 .TLB 扩展名。
您现在可以引用该 .TLB 文件并在不需要原始 DLL 的情况下进行构建,例如
#import "test.tlb" named_guids
【讨论】:
【参考方案5】:Visual Studio IDE 可以直接从非托管的 .exe 和 .dll 文件中提取二进制资源。 如果类型库作为二进制资源保存在 非托管 COM DLL(例如使用 VS 原生 C++ 编译器构建的)中,您可以按如下方式提取它:
-
在 VS 资源编辑器(打开可执行文件时的默认编辑器)中打开 .dll 文件。
导航到资源树中的类型库资源(
"TYPELIB"
,然后是1
)。
右键单击类型库资源并选择export
。这会弹出一个“将文件另存为”对话框。
在“文件另存为”框中,将文件名从默认(通常为bin1.bin
)更改为MyLibrary.tlb
之类的名称,然后点击确定。
使用OleView.exe
打开导出的.tlb 文件进行确认(结果应该与使用OleView.exe
打开.dll 看到的结果相同)。
要从 托管 DLL(例如,使用 C# 构建的那些)中提取类型库,VS 包含工具 Tlbexp.exe
(从 VS 命令提示符运行它):
https://msdn.microsoft.com/en-us/library/hfzzah2c(v=vs.110).aspx
【讨论】:
以上是关于如何从非托管 COM dll 生成类型库的主要内容,如果未能解决你的问题,请参考以下文章
从非托管 dll 文件(注入到正在运行的进程中)调用托管 dll
gcServer 设置未从非托管 exe 传递到托管 dll
从非托管 DLL 导入函数时,0x8007007F 是啥意思?