【问题标题】:What does stdole.dll do?stdole.dll 有什么作用?
【发布时间】:2010-09-14 18:59:11
【问题描述】:

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

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

将此文件拖入 GAC 会导致事件从指纹 COM 库中正常返回。

那么 stdole.dll 有什么作用呢?它的大小为 16k,所以它不会太多......它是某种链接到另一个库(如 STDOLE32)吗?为什么它的缺失会导致这种奇怪的行为?

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

【问题讨论】:

    标签: c# com stdole


    【解决方案1】:

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

    【讨论】:

    • 是的,我也在 PIA 目录中找到了一份副本。我们的应用不使用办公组件;这仍然不能解释我们所看到的行为!
    • 它可能使用“标准”COM 接口,如 IFont 或 IDispatch。似乎对.NET 中这些接口的支持需要引用stdole.dll。我很困惑为什么这个程序集与 Office 相关联。
    【解决方案2】:

    这里也讨论了这个问题: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?

    【讨论】:

      【解决方案3】:

      我认为其他任何答案实际上都没有回答大部分问题“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 来说不是必需的,显然微软在这种情况下是如何做到的。

      【讨论】:

        【解决方案4】:

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

        我不知道最初是如何在项目中引用这个的。这是一个旧版应用程序,所以肯定是很久以前的事了。

        西蒙

        【讨论】:

          【解决方案5】:

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

          <File Include="bin/stdole.dll"> ...
          

          删除该行(使用“在文件中查找”找到)并从远程服务器上的 bin 文件夹中删除 stdole.dll 解决了我的问题。

          希望这对其他人有所帮助。

          【讨论】:

            【解决方案6】:

            我还必须为 stdole 添加对我的项目的引用。尽管我没有对它的任何引用(它是一个简单的图像应用程序),但我们的 2 个用户收到了它丢失的错误。当这是一个 3.5 应用程序时,他们可能只运行 .net 2.0。我已经找到原因了。

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

            【讨论】:

            【解决方案7】:

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

            【讨论】:

              猜你喜欢
              • 2023-03-09
              • 1970-01-01
              • 2023-04-10
              • 2011-07-17
              • 2014-09-13
              • 2011-12-30
              • 1970-01-01
              • 2019-04-26
              • 2016-04-29
              相关资源
              最近更新 更多