Неглубокое понимание взаимодействия COM приводит к исключению TYPE_E_CANTLOADLIBRARY - в чем ошибка? - PullRequest
1 голос
/ 16 апреля 2020

У нас есть сборка. Net, A, которая использует класс Foo из библиотеки COM, B.

Мы создали взаимодействие для B (Interop.b.dll) и A использует Foo через взаимодействие.

Если я декомпилирую Interop.b.dll, я вижу следующий интерфейс, определенный в нем:

using System.Runtime.InteropServices;

namespace Interop.b
{
  [Guid("SOME-GUID")]
  [CoClass(typeof (FooClass))]
  [ComImport]
  public interface Foo : _Foo
  {
  }
}

В настройках ссылок. Net сборка A, у меня есть возможность встроить типы взаимодействия для Interop.b.dll. Если я установлю это на true, интерфейсы, определенные в Interop.b.dll, будут встроены в A.dll. Если я затем декомпилирую A.dll, я вижу тот же интерфейс, который я нашел во взаимодействии:

using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace Interop.b
{
  [CompilerGenerated]
  [Guid("SOME-GUID")]
  [CoClass(typeof (object))]
  [TypeIdentifier]
  [ComImport]
  public interface Foo : _Foo
  {
  }
}

За исключением того, что это не то же самое. В этой версии у нас есть [TypeIdentifier] в качестве дополнительного атрибута, а параметр атрибута CoClass изменился с typeof(FooClass) на typeof(object).

Я отмечаю, что Interop.b.dll содержит тип FooClass Я считаю, что это класс-оболочка для типа COM Foo, который отвечает за сортировку типов параметров между. Net и COM, но этот тип не был встроен в A.dll.

Внутри A.dll, Foo используется следующим образом:

using Interop.b;

namespace My.Product
{
    public class AClass: IAClass
    {
        private Foo LocalFoo { get; }

        public AClass()
        {
            LocalFoo = new Foo();
        }
    }
}

При чистой установке происходит сбой со следующим исключением:

System.InvalidCastException: Unable to cast COM object of type 'System.__ComObject' to interface type 'Interop.b.Foo'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{SOME-GUID}' failed due to the following error: Error loading type library/DLL. (Exception from HRESULT: 0x80029C4A (TYPE_E_CANTLOADLIBRARY)).

(Interop.b.dll установлено на GA C от установщика продукта)

На компьютере разработчика переустановка продукта и запуск из установленных двоичных файлов не выполняется аналогичным образом. После этого перекомпилируется продукт, который перезаписывает установленные двоичные файлы и работает либо из кода (в отладке), либо из двоичных файлов fre sh.

Теперь я считаю, что ошибка заключается в том, что код в A.dll должен быть экземпляр FooClass, а не Foo. то есть что-то вроде этого:

LocalFoo = new FooClass(); 

... потому что Foo - это интерфейс (во взаимодействии), а FooClass - это то, что обрабатывает сортировку типов параметров между. Net и COM.

Итак, вопросы:

1) Правильно ли я считаю, что код должен быть экземпляром FooClass, а не Foo?

2) Почему он работает вообще на компьютере разработчика?

3) Почему во встроенном интерфейсе используется typeof(object) вместо typeof(FooClass)?

4) В чем преимущество внедрения интерфейсов из взаимодействия в A.dll когда нам все еще понадобится Interop.b.dll на целевой машине, чтобы мы могли использовать FooClass?

...