views:

67

answers:

1

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"&gt;
<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>
+1  A: 

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:

<dependency>
   <dependentAssembly>
     <assemblyIdentity
       type="win32"
       name="Microsoft.Windows.Common-Controls"
       version="6.0.0.0"
       processorArchitecture="X86"
       publicKeyToken="6595b64144ccf1df"
       language="*"
     />
   </dependentAssembly>
</dependency>
Alex Shnayder