【问题标题】:Resolving .NET assembly mismatches in reflection with COM interop使用 COM 互操作解决反射中的 .NET 程序集不匹配问题
【发布时间】:2018-05-25 07:35:57
【问题描述】:

我正在尝试在 .Net 2.0 可执行文件中使用 .Net 4.6 库。

我使用了this COM approach,它一直有效,直到程序集 System.Collections.Immutable 得到解决。

我收到 ReflectionTypeLoadException 消息“无法加载文件或程序集 'System.Collections.Immutable, Version=1.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' 或其依赖项之一。定位程序集的清单定义确实与程序集引用不匹配。(来自 HRESULT 的异常:0x80131040)“

.Net 4.6 库使用 Roslyn 和 Roslyn 程序集引用 System.Collections.Immutable,Version=1.2.1.0。并且项目中引用了这个版本的程序集。但是 Roslyn 程序集(Microsoft.CodeAnalysis.CSharp,2.6.0.0 版)引用 System.Reflection.Metadata,Version=1.4.1.0 和元数据程序集引用 System.Collections.Immutable,Version=1.2.0.0

当我在 .Net 4.6 可执行文件而不是 .Net 2.0 中使用 .Net 4.6 库时,一切正常,没有例外。

我尝试将不可变程序集的“特定版本”设置为 false,但不起作用。 还尝试分离 .Net 2.0 和 .Net 4.6 文件夹,也不起作用。 .Net 4.6 library dll 和 Immutable dll 也在同一个文件夹中。

.Net 2.0 可执行文件的app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="Adapter" />
    </assemblyBinding>
  </runtime>
</configuration>

.Net 4.6 库的app.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0" />
      </dependentAssembly>
      ......other dependent assemblies....
    </assemblyBinding>
  </runtime>
</configuration>

.Net 2.0 可执行代码

static void Main()
{
    Console.WriteLine("CLR version from EXE: {0}", Environment.Version);
    Console.WriteLine("Is64BitProcess: {0}", (IntPtr.Size == 8));

    Type myClassAdapterType = Type.GetTypeFromProgID("Net4ToNet2Adapter.MyClassAdapter");
    object myClassAdapterInstance = Activator.CreateInstance(myClassAdapterType);
    IEnchanterAdapter myClassAdapter = (IEnchanterAdapter)myClassAdapterInstance;
    myClassAdapter.DoNet4Action();
}

.Net 4.6 库代码

[ComVisible(true)]
[Guid("E36BBF07-591E-4959-97AE-D439CBA392FB")]
public interface IMyClassAdapter
{
    void DoNet4Action();
}

[ComVisible(true)]
[Guid("A6574755-925A-4E41-A01B-B6A0EEF72DF0")]
public class MyClassAdapter : IMyClassAdapter
{
    private MyClass _myClass = new MyClass();

    public MyClassAdapter()
    {
        Console.WriteLine("adapter constructor");
    }

    public void DoNet4Action()
    {
        Console.WriteLine("CLR version from EXE: {0}", Environment.Version);
        Console.WriteLine("Is64BitProcess: {0}", Environment.Is64BitProcess);

        _myClass.DoNet4Action();
    }
}

class MyClass
{
    public void DoNet4Action()
    {
        var workspace = new AdhocWorkspace(); // throws exception here
    }
}

输出

CLR version from EXE: 2.0.50727.8794
Is64BitProcess: True
adapter constructor
CLR version from EXE: 4.0.30319.42000
Is64BitProcess: True

Fusion Assembly Binding Log(项目引用版本 1.2.2.0 时)(这同样适用于 .Net 4.6 可执行文件)

        FusionLog   "=== Pre-bind state information ===
LOG: DisplayName = System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a\n (Fully-specified)
LOG: Appbase = file:///D:/Develop/Enchanter/UnityWorkspace/bin/Debug/
LOG: Initial PrivatePath = NULL
Calling assembly : Microsoft.CodeAnalysis, Version=2.6.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: D:\\Develop\\Enchanter\\UnityWorkspace\\bin\\Debug\\UnityWorkspace.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\config\\machine.config.
LOG: Post-policy reference: System.Collections.Immutable, Version=1.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
LOG: Attempting download of new URL file:///D:/Develop/Enchanter/UnityWorkspace/bin/Debug/System.Collections.Immutable.DLL.
LOG: Attempting download of new URL file:///D:/Develop/Enchanter/UnityWorkspace/bin/Debug/System.Collections.Immutable/System.Collections.Immutable.DLL.
LOG: Attempting download of new URL file:///D:/Develop/Enchanter/UnityWorkspace/bin/Debug/Adapter/System.Collections.Immutable.DLL.
WRN: Comparing the assembly name resulted in the mismatch: Build Number
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
"   string

【问题讨论】:

  • 您是否尝试过在 app.config 文件中添加绑定重定向? docs.microsoft.com/en-us/dotnet/framework/configure-apps/…
  • 您只是看到了 .NET 4.x 的进程内并行 CLR 版本控制功能。实际上是为了解决使用 COM 的非托管主机程序的 DLL Hell,但我想不出为什么它不适用于 .NET 2.0 程序的主要原因。否则它不会解决您自己的 DLL Hell,如果您无法让您的代码同意使用该程序集的哪个版本,那么您需要在 .config 文件中使用 bindingRedirect。通常由 msbuild 自动生成,但在这里无济于事。
  • 在您再次删除之前,我曾短暂地看到 Fuslogvw 跟踪闪过。它告诉您要更改的 .config 文件。
  • 对不起,再次添加了融合日志,但它是针对版本 1.2.2.0(这是最新的)。然而它给出了几乎相同的错误
  • 在上面添加了 app.config

标签: .net com interop system.reflection


【解决方案1】:

程序集绑定重定向应该添加到 .Net 2.0 可执行文件手动,因为 Visual Studio 不会自动执行此操作,因为它们没有关系,因为COM 互操作。

.Net 2.0 可执行文件的新 app.config 是:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="Adapter" />
      <dependentAssembly>
        <assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-1.2.2.0" newVersion="1.2.2.0" />
      </dependentAssembly>
       ......other dependent assemblies....
    </assemblyBinding>
  </runtime>
</configuration>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-12
    • 2011-06-15
    • 2011-04-13
    • 1970-01-01
    • 1970-01-01
    • 2011-05-13
    • 1970-01-01
    • 2011-04-11
    相关资源
    最近更新 更多