我们有一个大型 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 中?
We have a large C# (.net 2.0) app which uses our own C++ COM component and a 3rd party fingerprint scanner library also accessed via COM. We ran into an issue where in production some events from the fingerprint library do not get fired into the C# app, although events from our own C++ COM component fired and were received just fine.
Using MSINFO32 to compare the loaded modules on a working system to those on a failing system we determined that this was caused by STDOLE.DLL not being in the GAC and hence not loaded into the faulty process.
Dragging this file into the GAC caused events to come back fine from the fingerprint COM library.
So what does stdole.dll do? It's 16k in size so it can't be much... is it some sort of link to another library like STDOLE32? How come its absence causes such odd behavior?
How do we distribute stdole.dll? This is an XCOPY deploy app and we don't use the GAC. Should we package it as a resource and use the System.EnterpriseServices.Internal.Publish.GacInstall to ensure it's in the GAC?
发布评论
评论(7)
在我们的项目中,IDispatch 使用了 stdole.dll。 我们将其更改为对象并删除 IDispatch,然后从引用中删除 stdole。
In our project IDispatch couses using stdole.dll. We've change it to object and remove IDispatch, then remove stdole from references.
看来 stdole.dll 是一个主要互操作程序集。 请参阅 MSDN 上的 Office 2003 主互操作程序集。
It seems that stdole.dll is a primary interop assembly. See Office 2003 Primary Interop Assemblies on MSDN.
我不认为任何其他答案实际上回答了大部分问题“stdole.dll 做什么”。 这是我的理解。
摘要:
该 DLL 位于从托管应用程序最终引导至非托管操作系统 DLL 的引用链的顶部附近,如下所示:
该链中的链接定义明确但模糊。 这个答案的其余部分沿着链走...
详细解释:
stdole.dll 本身是一个互操作 DLL。 这意味着它是一个 .NET 程序集,其目的本质上是 充当具有 COM 接口的特定非托管类的包装器。 如果您使用 ILSpy 或 dotPeek 等工具查看
stdole.dll
内部,您可以看到那里有什么。 这是StdPicture 的示例
接口:这一切都是一个接口,其属性对确实应该使用的 COM 类的详细信息进行编码。 像这样的 DLL 通常是使用
我们可以再深入一点。 上面示例中的
Guid
7BF80981-BF32-101A-8BBB-00AA00300CAB
通常可以在 Windows 注册表中找到,这就是运行时在 < code>stole.StdPicture 实际上是从托管代码中使用的。如果您使用 RegEdit 搜索该 GUID,您会发现:
其值为
00020430-0000-0000-C000-000000000046
。搜索该值,您会发现:(
同一 DLL 中的大多数其他 GUID 可能有类似的条目)。
这个密钥有很多有趣的细节,实际上是底层实现的几个版本的细节。 例如,在子项
2.0\0\win32
下,默认值为:版本 2 的 32 位变体。这距离
StdPicture
实际实现的位置更近了一步。TLB 文件只是 DLL 的一种 COM“标头”。 它本身没有可执行代码。 在 OLEViewDotNet 或原始 stdole2.tlb "https://learn.microsoft.com/en-us/windows/win32/com/ole-com-object-viewer" rel="noreferrer">OleView,可以读取typelib本身的IDL 。 在本例中,第一部分具有以下内容:
请注意,
uuid
具有与我们上面从 Regedit 获得的值相同的值。 向下滚动最终我们到达StdPicture
条目,与上面的示例相同:这里再次没有真正的代码,只有一个类定义。 回到RegEdit我们可以发现
uuid
:其值为
C:\Windows\System32\oleaut32.dll
。 现在我们知道这个 DLL 实现了 32 位stdole
库版本 2 的StdPicture
组件类。(虽然我认为这个文件应该在
SysWow64
...?)如果您要遵循此链来获取其他接口,您可能最终会得到相同的 DLL 或另一个。
请注意,对于某些语言(如 VB6),TLB 通常直接嵌入到实现 DLL 中。 但这对于 COM 来说不是必需的,而且显然 Microsoft 在本例中也不是这样做的。
I don't think any of the other answers actually answered most of the question "what does
stdole.dll
do". Here's my understanding.Summary:
This DLL is near the top of a chain of references leading from your managed application ultimately to unmanaged operating system DLLs which looks like this:
The links in this chain are well defined but obscure. The rest of this answer walks the chain...
Detailed explanation:
stdole.dll
itself is an interop DLL. That means that it is a .NET assembly whose purpose is to essentially act as a wrapper around specific unmanaged classes which have COM interfaces. If you look insidestdole.dll
with a tool like ILSpy or dotPeek you can see what's there. Here's an example for theStdPicture
interface:All this is is an interface with attributes that encode details of the COM classes that really should be used. DLLs like this are generally created automatically with a tool like
tlbimp.exe
or Visual Studio will do this for you when you add an unmanaged COM DLL directly to your project as a reference.We can dig a little deeper. A
Guid
in the example above7BF80981-BF32-101A-8BBB-00AA00300CAB
is generally going to be found in the Windows registry, that's where the runtime is going to look whenstole.StdPicture
is actually used from managed code.If you search for that GUID using RegEdit, you'll find:
which has the value
00020430-0000-0000-C000-000000000046
.Searching for that value, you'll find:
(Most of the other GUIDs from the same DLL would probably have a similar entry).
This key has a lot of interesting details, in fact details for several versions of the underlying implementation. For instance under subkey
2.0\0\win32
the default value is:for the 32-bit variant of version 2. That's one step closer to where
StdPicture
actually is implemented.A TLB file is just a COM "header" of sorts for a DLL. It doesn't have executable code in itself. Opening
stdole2.tlb
in a tool like OLEViewDotNet or the original OleView, you can read the IDL of the typelib itself. In this case, the first part has the following:Note the
uuid
has the same value we got from Regedit above. Scrolling down eventually we come to theStdPicture
entry, the same example as above:Yet again there's no real code here, just a class definition. Back to RegEdit we can find that
uuid
:whose value is
C:\Windows\System32\oleaut32.dll
. Now we know that this DLL implements theStdPicture
coclass for version 2 of the 32-bitstdole
library.(Though I would have thought this file should be in
SysWow64
...?)If you were to follow this chain for some other interface, you might end up at the same DLL or another.
Note that for some languages (like VB6) it is typical for the TLB to be embedded right in the implementing DLL directly. But this is not required for COM and obviously not how Microsoft did it in this case.
此处也讨论了此问题:为什么 Visual Studio 2015 将 stdole.dll 和 Microsoft.AnalysisServices.AdomdClient.dll 添加到我的项目中?< /a>
在本例中,将旧项目升级到 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 中设置嵌入互操作类型 true 和 false 有什么区别?This issue is also discussed over here: Why is Visual Studio 2015 adding stdole.dll and Microsoft.AnalysisServices.AdomdClient.dll to my project?
Upgrading an older project to VS 2015 is what caused stdole.dll to start getting included in the project in this case.
If the library referencing has the option to "Embed Interop Types" in the properies, this is preferred and the stdole.dll may not be needed after that. Just set
Embed Interop Types=true
in the properties of the reference.Libraries that allow this include the MS Office libraries such as Office, Excel, Core. An example of one that does not is Crystal Reports.
Hans Passant strongly discourages setting
Embed Interop Types=false
here: What's the difference setting Embed Interop Types true and false in Visual Studio?我有同样的问题。 我刚刚从应用程序中删除了引用并重新编译。 运行所有通过的测试。 然后在没有dll的情况下重新部署,一切正常。
我不知道这个项目最初是如何引用的。 这是一个遗留应用程序,所以一定是很久以前的事了。
西蒙
I had the same problem. I just deleted the reference from the application and recompiled. Ran all the tests which passed. Then redeployed without the dll and it all worked.
I dont know how a reference to this got in the project in the first place. It is a legacy app so must have been a long time ago.
Simon
就我而言,它是对 Office Word Interop 的旧的未使用引用...但删除它还不够:发布配置文件仍然有复制 stdole.dll 的行!
删除该行(使用“在文件中查找”找到)并从远程服务器上的 bin 文件夹中删除 stdole.dll 解决了我的问题。
希望这对其他人有帮助。
In my case, it was an old unused reference to Office Word Interop ... but removing that was not sufficient: The publish profile still had line to copy stdole.dll !
Deleting that line (found using 'Find in Files') and deleting the stdole.dll from the bin folder on the remote server fixed my problem.
Hope this helps someone else.
我还必须为 stdole 添加对我的项目的引用。 尽管我没有任何对它的引用(它是一个简单的图像应用程序),但我们的 2 位用户收到了它丢失的错误。 可能他们只运行 .net 2.0,而这是 3.5 应用程序。 我已经明白为什么了。
我还进入项目属性选项卡进行发布,并选择应用程序文件,然后包含要部署的 stdole。 希望这会起作用。
I had to also add a reference to my project for stdole. Even though I don't have any references to it (it's a simple image app), 2 of our users were getting errors that it was missing. It could be that they were only running .net 2.0 when this is a 3.5 app. I have figured out why.
I also went in to publish on the project properties tab, and selected Application Files, then included the stdole to be deployed. Hopefully that will work.