Почему частная сборка, используемая моим COM-компонентом, не найдена?

Мое приложение создает экземпляр COM-компонента (глобальная регистрация).
Этот COM-компонент создает экземпляры компонентов без регистрации.
Один из этих подкомпонентов реализован на C#.
Если мое приложение не находится в той же папке, что и основной COM-компонент, ему не удалось создать экземпляр C# COM-компонента (но успешно для других COM-компонентов).

ВНИМАНИЕ: подробные пояснения ниже...

У меня есть приложение (Loader1), которое загружает COM-компонент (COM1, который не требует регистрации), и этот COM-компонент также загружает несколько других COM-компонентов (которые сами по себе не требуют регистрации).

  • Loader1
    • COM1
      • COM2
      • COM3
      • COM4
      • и т.д ...

Но я должен поддерживать сценарий, в котором загрузчик использует компонент COM1 как обычный и зарегистрированный компонент COM.
Это работает уже несколько лет без проблем (просто нужно было разобраться с манифестным адом).

Теперь мы разработали новый COM-компонент на C# (COM-взаимодействие). Этот компонент также был сделан без регистрации (немного другая зависимость от сборки, но работает нормально).

Итак, мы получили:

  • Loader1
    • COM1
      • COM2
      • COM#

Loader1 получил манифест, указывающий, что он использует COM1.
COM1 получил манифест, указывающий, что он использует COM2 и COM#.
Все находится в одном каталоге и работает безупречно.

ТЕПЕРЬ, когда я пытаюсь использовать другой загрузчик (Loader2), который использует COM1 как ОБЫЧНЫЙ COM-компонент (COM1 зарегистрирован в системе и находится в другом каталоге), ему не удается установить COM#.
Чтобы быть более точным, COM1 зарегистрирован в системе, а COM2 и COM# — нет (это частные сборки, используемые только COM1).

Подводя итоги проблемы:

Loader2 в своей папке создает экземпляр COM1 как обычный компонент COM.
COM1 в своей папке получил приватные сборки, COM2, COM#. Эти частные сборки находятся в папке COM1.
COM1 успешно создает экземпляр COM2.
COM1 не удалось создать экземпляр COM#.

HRESULT возвращается, если 0x80070002, HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND).
Когда я использую FUSLOGVW.exe, чтобы увидеть, что делает загрузчик .net, кажется, что .net ищет COM# в папке приложения (папка Loader2), а не COM1 папка.
Почему-то манифест COM1 не используется при поиске COM#.
Но он используется при поиске COM2...

Ну это разные системы.

Теперь, если я скопирую файлы Loader2 в папку, где находится COM1 и его зависимости. Все работает нормально.

Итак, есть идеи, как помочь загрузчику сборки .net найти частную сборку COM# из папки COM1, а не из папки приложения?


person Julianis    schedule 06.08.2019    source источник
comment
Это кажется вполне логичным. Я не понимаю, почему система загружает компонент из какого-то случайного места (я знаю, что это не случайно, но каталог Loader1 ничего не значит для контекста приложения Loader2). Например, вы можете указать относительный частный путь при загрузке компонентов: docs.microsoft.com/en-us/windows/win32/sbscs/ (см. раздел "зондирование"), поэтому либо они прописаны, либо находятся там, где указано (примечание: дополнительные каталоги не должны быть подкаталогами каталога сборки.)   -  person Simon Mourier    schedule 06.08.2019
comment
Что ж, Loader1, использующий COM1 как частную сборку, не является проблемой, и именно по этой причине Loader1 и COM1 находятся в одном каталоге. Допустим, Loader1/2 использует COM1 в качестве стандартного COM-компонента, расположенного в его собственной папке. Затем COM1 использует изоляцию COM и частные сборки. Бесплатная регистрация COM работает для стандартных компонентов COM (когда COM1 создает экземпляр COM2, он ищется в папке COM1, а не в реестре). Но, к сожалению, это не работает для компонентов С# COM.   -  person Julianis    schedule 07.08.2019
comment
Ну, я нашел похожий вопрос: stackoverflow.com/questions/48272723/ Кажется, решения нет   -  person Julianis    schedule 07.08.2019
comment
Я нашел решение, пройдя через API хостинга и создав AppDomain. COM1 создает AppDomain и настраивает его для использования с COM#. Затем он создает экземпляр C# нужного сокласса (он создает непосредственно объект C#). Затем из _ObjectHandle я получаю интерфейс COM. Таким образом, он пропускает CoCreateInstance() ... Кажется, он работает независимо от загрузчика: родной, .net, изолированный или нет.   -  person Julianis    schedule 08.08.2019