Ошибка COR_E_NEWER_RUNTIME при создании класса COM из соседней сборки

У меня следующая ситуация:

  • Нативное приложение Delphi должно вызывать COM-интерфейс из C# DLL
  • Я хочу сделать сотрудничество приложения и DLL без регистрации C# DLL (бок о бок)

Код приложения Delphi (исполняемый файл консоли):

program TestSideBySide2;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  mscorlib_TLB in 'mscorlib_TLB.pas',
  TestSideBySide2_TLB in 'TestSideBySide2_TLB.pas';

var
   sideBySide : TestSideBySide2_TLB._SideBySideClass;
   intfSideBySide : TestSideBySide2_TLB.ISideBySideClass;
   res : HRESULT;

begin
  try
      sideBySide := TestSideBySide2_TLB.CoSideBySideClass.Create();
      res := sideBySide.QueryInterface(IID_ISideBySideClass,intfSideBySide);

      Writeln(intfSideBySide.Version());

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Импортированный 'TestSideBySide2_TLB.pas' был сгенерирован из DLL с использованием TLIBIMP.exe инструмент.

Вот манифест приложения, который будет связан с приложением Delphi в качестве ресурса:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"
          xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
  <assemblyIdentity 
    type="win32"
    name="TestSideBySide.exe"
    version = "1.0.0.0" />
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
        type="win32"
        name="TestSideBySide2"
        version="1.0.0.0" />
    </dependentAssembly>
  </dependency>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="asInvoker"
          uiAccess="false"/>
        </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

C# DLL код (скомпилирован с использованием SharpDevelop)

using System;
using System.Reflection;
using System.Runtime.InteropServices;

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: Guid("07F9C367-BFA4-45AD-8A60-689096BD7AA9")]

namespace TestSideBySide2
{

    /// <summary>
    /// Exposed interface.
    /// </summary>
    [Guid("49D49031-12D8-40B5-85FA-B42133FD7DD0")]
    public interface ISideBySideClass
    {
        string Version();
    }

    /// <summary>
    /// Implementation of exposed interface.
    /// </summary>
    [Guid("A0BDB20B-A6E4-4A36-A64C-CC9186DD1C3E")]
    public class SideBySideClass : ISideBySideClass
    {
        public string Version()
        {
            return "1.0.0-C#";
        }
    }
}

И манифест сборки (также связанный как ресурс в DLL):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" 
  manifestVersion="1.0">
    <assemblyIdentity
                type="win32"
                name="TestSideBySide2"
                version="1.0.0.0" />
    <clrClass
                clsid="{A0BDB20B-A6E4-4A36-A64C-CC9186DD1C3E}"
                progid="TestSideBySide2"
                threadingModel="Both"
                name="TestSideBySide2.SideBySideClass" >
    </clrClass>
</assembly>

Пока все довольно просто. Приложение Delphi может разрешить привязки, и DLL будет загружена. Но линия

sideBySide := TestSideBySide2_TLB.CoSideBySideClass.Create();

терпит неудачу с исключением

EOleSysError: OLE-Error 8013101B, ClassID: {A0BDB20B-A6E4-4A36-A64C-CC9186DD1C3E}

Код ошибки разрешается в COR_E_NEWER_RUNTIME,


Я проверил версию среды выполнения.NET, для которой была создана DLL, и это.NET 4.0 (которая доступна в моей среде Windows 10).

Затем я попытался собрать DLL для более старых версий времени выполнения (2.0, 3.0, 3.5), и для каждой из них это работало просто отлично.


Конечно, я исследовал, в чем может быть проблема, и вот что я нашел до сих пор обещающим решить проблему (но не сделал):

В настоящее время у меня нет идей, что еще можно сделать. Любые дополнительные ресурсы, которые я нашел в Интернете, просто указывают на одно из перечисленных выше предложений.

Что еще я мог пропустить там?


Обновить:

Коллега отметил, что это может быть странность Delphi и вызов из неуправляемого кода.

Мы используем Embarcadero Сиэтл Delphi 10.

1 ответ

Решение

Я решил проблему с помощью информации, найденной здесь:

Версии и ошибки времени выполнения 0x80131700 и 0x8013101b

Я уже сделал попытку добавить версию.NET CLR в манифест сборки DLL. Это может быть сделано для каждого класса в clrClass раздел. Чего я не знал, так это того, что runtimeVersion Атрибут должен быть полностью квалифицированным.

Полный clrClass Теперь раздел выглядит так:

<clrClass
            clsid="{A0BDB20B-A6E4-4A36-A64C-CC9186DD1C3E}"
            progid="TestSideBySide2"
            threadingModel="Both"
            name="TestSideBySide2.SideBySideClass" 
            runtimeVersion="v4.0.30319">
</clrClass>

Согласно документу, указанному выше, записи версий для других версий CLR должны быть:

  • v1.0.3705
  • v1.1.4322
  • v2.0.50727
  • v4.0.30319
Другие вопросы по тегам