stdole.dll做什么用?

时间:2008-10-02 12:34:04

标签: c# com stdole

我们有一个大型的C#(。net 2.0)应用程序,它使用我们自己的C ++ COM组件和通过COM访问的第三方指纹扫描程序库。我们遇到了一个问题,在生产过程中,指纹库中的一些事件不会被C#应用程序触发,尽管来自我们自己的C ++ COM组件的事件被触发并且收到的很好。

使用MSINFO32将工作系统上加载的模块与发生故障的系统上的模块进行比较,我们确定这是因为STDOLE.DLL不在GAC中,因此没有加载到故障过程中。

将此文件拖到GAC中会导致事件从指纹COM库恢复正常。

那么stdole.dll做什么?它的大小是16k所以它不能太多......它是否与STDOLE32这样的另一个库有某种联系?它的缺席怎么会导致这种奇怪的行为?

我们如何分发stdole.dll?这是一个XCOPY部署应用程序,我们不使用GAC。我们应该将它打包为资源并使用System.EnterpriseServices.Internal.Publish.GacInstall来确保它在GAC中吗?

7 个答案:

答案 0 :(得分:22)

似乎stdole.dll是主互操作程序集。见Office 2003 Primary Interop Assemblies on MSDN.

答案 1 :(得分:3)

此问题也在这里讨论:Why is Visual Studio 2015 adding stdole.dll and Microsoft.AnalysisServices.AdomdClient.dll to my project?

将旧项目升级到VS 2015是导致stdole.dll在这种情况下开始包含在项目中的原因。

如果库引用在选项中具有“嵌入互操作类型”选项,则首选此选项,之后可能不需要stdole.dll。只需在引用的属性中设置Embed Interop Types=true即可。

允许此功能的库包括MS Office库,如Office,Excel,Core。一个没有的例子是Crystal Reports。

Hans Passant 强烈反对在此设置Embed Interop Types=falseWhat's the difference setting Embed Interop Types true and false in Visual Studio?

答案 2 :(得分:2)

我遇到了同样的问题。我刚从应用程序中删除了引用并重新编译。跑过所有通过的测试。然后在没有dll的情况下重新部署,这一切都有效。

我不知道如何在项目中首先提到这一点。它是一个遗留应用程序,所以必须在很久以前。

西蒙

答案 3 :(得分:0)

我还必须添加对我的stdole项目的引用。即使我没有任何引用它(它是一个简单的图像应用程序),我们的2个用户遇到了它丢失的错误。可能是因为这是3.5应用程序时它们只运行.net 2.0。我弄明白了为什么。

我还在项目属性选项卡上发布,并选择了应用程序文件,然后包含要部署的stdole。希望这会奏效。

答案 4 :(得分:0)

在我们的项目IDispatch中使用stdole.dll。我们将其更改为object并删除IDispatch,然后从引用中删除stole。

答案 5 :(得分:0)

在我的情况下,它是一个旧的未使用的Office Word Interop引用...但删除它是不够的:发布配置文件仍然有行复制stdole.dll!

Query query = FirebaseDatabase.getInstance()
            .getReference()
            .child("groups").orderByChild("currentMembers").equalTo(currentUserID);

    FirebaseRecyclerOptions<UserGroup> options =
            new FirebaseRecyclerOptions.Builder<UserGroup>()
                    .setQuery(query, UserGroup.class)
                    .build();

删除该行(使用&#39;在文件中查找&#39;)并从远程服务器上的bin文件夹中删除stdole.dll修复了我的问题。

希望这有助于其他人。

答案 6 :(得分:0)

我认为其他任何答案实际上都没有回答“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 可能具有类似的条目)。

这个key有很多有趣的细节,实际上是底层实现的几个版本的细节。例如在子键 2.0\0\win32 下,默认值为:

C:\WINDOWS\SysWow64\stdole2.tlb

对于版本 2 的 32 位变体。这离实际实现 StdPicture 的位置更近了一步。


TLB 文件只是 DLL 的各种 COM“头文件”。它本身没有可执行代码。在像 OLEViewDotNet 或原始 OleView 这样的工具中打开 stdole2.tlb,您可以读取 typelib 本身的 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 位 StdPicture 库的第 2 版实现了 stdole coclass。

(虽然我认为这个文件应该在 SysWow64...?)

如果您要为其他接口遵循此链,您可能最终会使用同一个 DLL 或其他。

请注意,对于某些语言(如 VB6),通常将 TLB 直接嵌入到实现 DLL 中。但这不是 COM 所必需的,而且显然不是微软在这种情况下是如何做到的。