使用 SxS 和清单文件时,.net 调用 COM 进而调用其他 .net COM 对象是否有效
我有一个 .net 应用程序调用 COM 组件 (C++),该组件又调用 .NET 中实现的另一个 COM 对象。
此应用程序使用 Windows SxS 功能,并且不注册任何 COM 组件。不是用 C++ 编写的,也不是用 .net 编写的。
对 C++ COM 组件的第一次调用工作正常。但是,当 C++ COM 组件调用 .net 组件时,它会失败,类未注册。
我尝试使用清单文件创建一个小型 C++ 应用程序,该文件调用 .net 组件并且它可以工作。 看来当流量是.net时->通讯本机 -> .NET COM。然后SxS 就坏了并且无法工作。
在查看 Fusion Logs(程序集加载日志)时,我发现甚至没有人尝试解析 .NET COM 程序集。
这个 SxS 场景是否应该有效(我认为它应该有效)?如果是,那么我做错了什么?
这些是我正在使用的清单文件。
.net 应用程序的应用程序清单(作为资源嵌入):
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<file name="DotNetComConsumer.dll" hashalg="SHA1">
<comClass clsid="{44E69FC9-5EAF-4D57-8C09-430F703AD82F}" tlbid="{4F81C9C3-FDDF-48F6-BC25-6F8CD458EBE6}"/>
<typelib tlbid="{4F81C9C3-FDDF-48F6-BC25-6F8CD458EBE6}" resourceid="1" version="2.0" helpdir="" flags="HASDISKIMAGE"/>
</file>
<comInterfaceExternalProxyStub name="_Class1" iid="{5D41351A-440B-4175-9296-72D5EED83AA7}" tlbid="{4F81C9C3-FDDF-48F6-BC25-6F8CD458EBE6}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="application.sxs" version="1.0.0.0" />
</dependentAssembly>
</dependency>
</asmv1:assembly>
application.sxs.manifest(常规文件):
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="application.sxs" version="1.0.0.0"/>
<dependency>
<dependentAssembly>
<assemblyIdentity name="PerformanceMonitor" version="10.0.0.9999" publicKeyToken="792843134cf0407a" processorArchitecture="msil"/>
</dependentAssembly>
</dependency>
</assembly>
PerformanceMonitor 清单(作为 PerformanceMonitor.dll 中的资源嵌入,以解决 XP 中的 .net com bug):
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="PerformanceMonitor" version="10.0.0.9999" publicKeyToken="792843134cf0407a" processorArchitecture="msil"></assemblyIdentity>
<clrClass clsid="{AA614438-BC7D-400c-8837-525BFBB7253A}" progid="PerformanceMonitorFactory" threadingModel="Both" name="PerformanceMonitorFactory" runtimeVersion="v2.0.50727"></clrClass>
<file name="PerformanceMonitor.dll" hashalg="SHA1"/>
</assembly>
I have a .net application calling to a COM component (C++) which in turn calls to another COM object implemented in .NET.
This application is using Windows SxS capabilities and does not register any of it's COM components. Not the one written in C++, and not the one written in .net.
This first call to the C++ COM component works fine. But when the C++ COM component calls to the .net one, it fails with class not registered.
I have tried creating a small C++ app with a manifest file which calls the .net component and it works.
It seems that when the flow is .net -> COM NATIVE -> .NET COM. Then SxS breaks and does not work.
When looking at Fusion Logs (assembly loading logs) I see that no one is even attempting to resolve the .NET COM assembly.
Is this SxS scenario even supposed to work (I think it does supposed to work)? If yes, then what can I be doing wrong ?
These are the manifest files I'm using.
The app manifest for the .net application (embeded as resource):
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<file name="DotNetComConsumer.dll" hashalg="SHA1">
<comClass clsid="{44E69FC9-5EAF-4D57-8C09-430F703AD82F}" tlbid="{4F81C9C3-FDDF-48F6-BC25-6F8CD458EBE6}"/>
<typelib tlbid="{4F81C9C3-FDDF-48F6-BC25-6F8CD458EBE6}" resourceid="1" version="2.0" helpdir="" flags="HASDISKIMAGE"/>
</file>
<comInterfaceExternalProxyStub name="_Class1" iid="{5D41351A-440B-4175-9296-72D5EED83AA7}" tlbid="{4F81C9C3-FDDF-48F6-BC25-6F8CD458EBE6}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="application.sxs" version="1.0.0.0" />
</dependentAssembly>
</dependency>
</asmv1:assembly>
application.sxs.manifest (regular file):
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="application.sxs" version="1.0.0.0"/>
<dependency>
<dependentAssembly>
<assemblyIdentity name="PerformanceMonitor" version="10.0.0.9999" publicKeyToken="792843134cf0407a" processorArchitecture="msil"/>
</dependentAssembly>
</dependency>
</assembly>
PerformanceMonitor manifest (embeded as resource in PerformanceMonitor.dll to work around .net com bug in XP):
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="PerformanceMonitor" version="10.0.0.9999" publicKeyToken="792843134cf0407a" processorArchitecture="msil"></assemblyIdentity>
<clrClass clsid="{AA614438-BC7D-400c-8837-525BFBB7253A}" progid="PerformanceMonitorFactory" threadingModel="Both" name="PerformanceMonitorFactory" runtimeVersion="v2.0.50727"></clrClass>
<file name="PerformanceMonitor.dll" hashalg="SHA1"/>
</assembly>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
它确实有效,但有些事情可能会破坏它(正如我发现的)。
显然,如果您的应用程序是 WinForms 应用程序,并且它使用 Application.EnableVisualStyles 命令使用操作系统提供的视觉样式,同时使用清单文件创建激活上下文,那么您就陷入了困境。
看来(根据这个) 此命令本身会创建一个激活上下文以重定向进程以使用 Microsoft.Windows.Common-Controls 版本 6.0.0.0。
由于某种原因,这会破坏您在清单文件中定义的 .net com 对象的使用。
从应用程序中删除 Application.EnableVisualStyles 并将其替换为清单文件中的此依赖项似乎可以解决问题:
It does work, but there are things that can break it (as I have found out).
Apparently, if your application is a WinForms application, and it uses Application.EnableVisualStyles command to use visual styles provided by the OS, and at the same time uses manifest files to create an activation context, then you are in a pickle.
It seems (according to this) this command in itself creates an activation context to redirect process to use Microsoft.Windows.Common-Controls version 6.0.0.0.
And for some reason this breaks usage of the .net com object you define in you manifest file.
Removing Application.EnableVisualStyles from application, and replacing it with this dependency in the manifest file seems to do the trick: