我认为其他任何答案实际上都没有回答大部分问题“stdole.dll 做了什么”。这是我的理解。
总结:
此 DLL 位于从您的托管应用程序最终指向非托管操作系统 DLL 的引用链的顶部,如下所示:
.NET app -->
stdole.dll -->
stdole2.tlb -->
oleaut32.dll
这个链条中的链接定义明确但晦涩难懂。这个答案的其余部分走链......
详细解释:
stdole.dll 本身就是一个互操作 DLL。这意味着它是一个 .NET 程序集,其目的本质上是 act as a wrapper 围绕具有 COM 接口的特定非托管类。如果您使用 ILSpy 或 dotPeek 之类的工具查看 stdole.dll 内部,您可以看到那里有什么。这是StdPicture 接口的example:
using System.Runtime.InteropServices;
namespace stdole
{
[CoClass(typeof (StdPictureClass))]
[Guid("7BF80981-BF32-101A-8BBB-00AA00300CAB")]
[ComImport]
public interface StdPicture : Picture
{
}
}
这只是一个接口,其属性编码了真正应该使用的 COM 类的详细信息。像这样的 DLL 通常是使用 tlbimp.exe 之类的工具自动创建的,或者当您将非托管 COM DLL 作为参考直接添加到项目中时,Visual Studio 会为您执行此操作。
我们可以再深入一点。上例中的Guid 7BF80981-BF32-101A-8BBB-00AA00300CAB 通常会在 Windows 注册表中找到,这是在托管代码中实际使用 stole.StdPicture 时运行时要查看的位置。
如果您使用 RegEdit 搜索该 GUID,您会发现:
Computer\HKEY_CLASSES_ROOT\Interface\{7BF80981-BF32-101A-8BBB-00AA00300CAB}\TypeLib
其值为00020430-0000-0000-C000-000000000046。
搜索那个值,你会发现:
Computer\HKEY_CLASSES_ROOT\TypeLib\{00020430-0000-0000-C000-000000000046}
(来自同一 DLL 的大多数其他 GUID 可能会有类似的条目)。
这个键有很多有趣的细节,实际上是底层实现的几个版本的细节。例如子键2.0\0\win32 下的默认值为:
C:\WINDOWS\SysWow64\stdole2.tlb
对于版本 2 的 32 位变体。这更接近实际实现 StdPicture 的位置。
TLB 文件只是 DLL 的 COM“头”。它本身没有可执行代码。在OLEViewDotNet 或原始OleView 之类的工具中打开stdole2.tlb,您可以读取类型库本身的IDL。在这种情况下,第一部分具有以下内容:
// typelib filename: stdole2.tlb
[
uuid(00020430-0000-0000-C000-000000000046),
version(2.0),
helpstring("OLE Automation")
]
library stdole
{
...
}
请注意,uuid 的值与我们从上面的 Regedit 中获得的值相同。向下滚动最终我们来到StdPicture 条目,与上面的示例相同:
[
uuid(0BE35204-8F91-11CE-9DE3-00AA004BB851)
]
coclass StdPicture {
...
};
这里没有真正的代码,只是一个类定义。回到RegEdit我们可以找到uuid:
Computer\HKEY_CLASSES_ROOT\CLSID\{0BE35204-8F91-11CE-9DE3-00AA004BB851}\InprocServer32
其值为C:\Windows\System32\oleaut32.dll。现在我们知道这个 DLL 为 32 位 stdole 库的第 2 版实现了 StdPicture coclass。
(虽然我以为这个文件应该在SysWow64...?)
如果您要遵循此链获取其他接口,您可能最终会使用相同的 DLL 或另一个。
请注意,对于某些语言(如 VB6),TLB 通常直接嵌入到实现的 DLL 中。但这对于 COM 来说不是必需的,显然微软在这种情况下是如何做到的。