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

  • Собственное приложение 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 Seattle Delphi 10.

2
user0042 21 Июл 2017 в 17:24
1
В этом кратком сообщении в блоге MSDN рассказывается об ошибке COR_E_NEWER_RUNTIME.
 – 
Ron
22 Июл 2017 в 18:37
1
Здесь скрывается (менее краткая) и интересная информация: blogs.msdn.com/b/junfeng/archive/2006/05/17/… THX! ;-)
 – 
user0042
22 Июл 2017 в 18:40
Спасибо еще раз. Ссылка, которую вы мне дали, наконец привела меня к правильному решению.
 – 
user0042
24 Июл 2017 в 12:59

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
1
user0042 24 Июл 2017 в 12:58