Загрузка незарегистрированной сборки.NET из неуправляемой нативной библиотеки C++ в приложении Java

Я использую приложение Java, которое может быть расширено с помощью пользовательских пакетов, которые могут включать в себя собственный код, поэтому я не имею никакого контроля над средой Java, кроме возможности добавления расширений jar.

В этом случае мне нужно иметь возможность вызывать код C# из расширения Java. Это код C#, который ранее использовался из чисто нативного контекста с использованием свободного от регистрации COM - который отлично работает. Теперь мне нужно иметь возможность сделать такой же код пригодным для использования из этого контекста Java, но я столкнулся с проблемой, что, похоже, нет никакого способа контролировать, где должна быть найдена DLL. Требование установки DLL в каталог bin JRE/JDK явно не вариант, и требование регистрации DLL в GAC не было бы идеальным.

В настоящее время я надеюсь, что все зависимости DLL будут упакованы в jar-файл расширения и будут загружаться при необходимости во время выполнения (без установки вручную).

Я надеялся, что смогу использовать API контекста активации, чтобы это заработало, и протестировал несколько вариантов этого кода с помощью DLL в D: \ somepath \:

ACTCTX actctx = {sizeof(actctx)};
actctx.lpSource = "D:\\somepath\\dll.manifest";
actctx.lpAssemblyDirectory = "D:\\somepath\\";
actctx.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;

HANDLE hActCtx = CreateActCtx(&actctx);
ULONG_PTR ulpCookie = 0;
ActivateActCtx(hActCtx, &ulpCookie);

CoCreateInstance(...);

Манифест содержит единственную зависимую сборку с деталями сборки, содержащей класс C#, на который ссылается вызов CoCreateInstance.

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity name="[assemblyname]" processorArchitecture="msil" publicKeyToken="[token]" version="[version]" />
    </dependentAssembly>
  </dependency>
</assembly>

Также пробовал с манифестом в этом формате, выгруженным из DLL с помощью mt.exe:

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity name="[assemblyname]" version="[version]" publicKeyToken="[token]" processorArchitecture="msil"/>
    <clrClass clsid="..." progid="..." threadingModel="Both" name="..." runtimeVersion="v4.0.30319"/>
    ...
    <file name="[assemblyname].dll" hashalg="SHA1"/>
</assembly>

Вызовы CreateActCtx и ActivateActCtx успешны, но вызов CoCreateInstance всегда терпит неудачу, возвращая 0x80070002, если я не помещаю DLL в C:\Program Files\Java...

Есть ли какое-либо решение (кроме использования GAC), которое позволило бы полностью неуправляемой C++ DLL загрузить и создать экземпляр класса C# из DLL в произвольном известном месте?

1 ответ

Я работаю над приложением с аналогичными требованиями, т.е. мне нужно активировать управляемый COM-сервер без регистрации (нашел его в DLL, написанном на C#/.net v4.8) из неуправляемого клиентского процесса (написанного на C++), а C# DLL должна находиться в каталоге вне каталога приложения C++.

На данный момент бесплатная активация COM-сервера управляемой DLL-библиотеки COM-сервера работает для меня только тогда, когда я

  • активировать COM-сервер с помощью пользовательского контекста активации (CreateActCtx / ActivateActCtx и т. д.) с помощьюactctx.lpAssemblyDirectory = ...установить в каталог COM DLL и

  • изменить , чтобы он мог найти мою C# DLL, чего он не делает по умолчанию.

Что касается последнего, в настоящее время я делаю это, добавляя для C++ EXE, в котором я активирую режим разработки , а также устанавливаю для переменной среды DEVPATH то же значение, что и для `actctx.lpAssemblyDirectory'. Это работает для меня, потому что мне нужно, чтобы каталог C# DLL находился вне каталога C++ EXE во время разработки.

Обратите внимание, что существуют и другие варианты изменения алгоритм проверки сборки на стороне .netалгоритма проверки сборки .net . Например, вы могли бы

Возможно (если это вариант для вас) взгляните на .Net DllExport , который позволяет вам экспортировать методы .net как функции DLL из сборки .net. Это позволяет вам взаимодействовать со сборкой .net так же, как с собственной библиотекой DLL (используя LoadLibrary, GetProcAddress и т. д.).

Другие вопросы по тегам