44

我们有一个大型 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 中?

4

7 回答 7

23

似乎 stdole.dll 是一个主要的互操作程序集。请参阅MSDN 上的 Office 2003 主要互操作程序集。

于 2008-10-02T12:51:47.873 回答
4

此处还讨论了此问题:为什么 Visual Studio 2015 将 stdole.dll 和 Microsoft.AnalysisServices.AdomdClient.dll 添加到我的项目中?

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

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

允许这样做的库包括 MS Office 库,例如 Office、Excel、Core。Crystal Reports 就是一个例子。

Hans Passant 强烈反对Embed Interop Types=false在此处设置:在 Visual Studio 中设置 Embed Interop Types true 和 false 有何不同?

于 2016-09-21T17:55:39.363 回答
3

我认为其他任何答案实际上都没有回答“做stdole.dll什么”的大部分问题。这是我的理解。

概括:

此 DLL 位于从托管应用程序最终指向非托管操作系统 DLL 的引用链的顶部附近,如下所示:

    .NET app -->
        stdole.dll -->
            stdole2.tlb -->
                oleaut32.dll

这条链中的链接定义明确但晦涩难懂。这个答案的其余部分走链......


详细解释:

stdole.dll它本身就是一个互操作 DLL。这意味着它是一个 .NET 程序集,其目的基本上是充当具有 COM 接口的特定非托管类的包装器。如果您使用ILSpy或 dotPeek 之stdole.dll类的工具查看内部,您可以看到里面有什么。下面是一个接口示例StdPicture

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上面示例中的A7BF80981-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 可能会有类似的条目)。

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

C:\WINDOWS\SysWow64\stdole2.tlb

对于版本 2 的 32 位变体。这更接近StdPicture实际实现的位置。


TLB 文件只是 DLL 的 COM“头”。它本身没有可执行代码。在OLEViewDotNet或原始OleViewstdole2.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 实现StdPicture了 32 位stdole库版本 2 的 coclass。

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

如果您要按照此链获取其他接口,您可能最终会使用相同的 DLL 或另一个。

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

于 2021-06-28T17:35:16.613 回答
2

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

我不知道首先在项目中是如何引用这个的。这是一个遗留应用程序,所以一定是很久以前的事了。

西蒙

于 2010-04-03T08:51:05.830 回答
1

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

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

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

希望这对其他人有帮助。

于 2018-03-20T01:52:03.257 回答
0

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

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

于 2009-08-19T15:24:26.203 回答
0

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

于 2013-06-07T09:32:11.890 回答