Работает ли .net, вызывающий COM, который, в свою очередь, вызывает другой COM-объект .net, когда используется SxS и используются файлы манифеста - PullRequest
4 голосов
/ 07 апреля 2010

У меня есть приложение .net, вызывающее COM-компонент (C ++), который, в свою очередь, вызывает другой COM-объект, реализованный в .NET.

Это приложение использует возможности Windows SxS и не регистрирует ни один из его COM-компонентов. Не тот, что написан на C ++, и не тот, что написан на .net.

Этот первый вызов компонента C ++ COM работает нормально. Но когда COM-компонент C ++ вызывает .net, происходит сбой, когда класс не зарегистрирован.

Я попытался создать небольшое приложение C ++ с файлом манифеста, который вызывает компонент .net, и он работает. Кажется, что когда поток .net -> COM NATIVE -> .NET COM. Тогда SxS ломается и не работает.

При просмотре журналов Fusion (журналов загрузки сборок) я вижу, что никто даже не пытается разрешить сборку .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 для обхода ошибки .net com в 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 Ответ

6 голосов
/ 17 мая 2010

Это работает, но есть вещи, которые могут его сломать (как я выяснил).

Очевидно, если ваше приложение является приложением WinForms и использует команду Application.EnableVisualStyles для использования визуальных стилей, предоставляемых ОС, и в то же время использует файлы манифеста для создания контекста активации, Вы в рассоле.

Кажется (согласно this ) эта команда сама по себе создает контекст активации для перенаправления процесса на использование Microsoft.Windows.Common-Controls версии 6.0.0.0. И по какой-то причине это нарушает использование объекта .net com, который вы определили в файле манифеста.

Удаление Application.EnableVisualStyles из приложения и замена его на эту зависимость в файле манифеста, похоже, помогает:

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