Loading unregistered .NET assembly from unmanaged native C++ library within Java application

0

I am using a Java application that can be extended with custom packages that may include native code, as such I have no control over the Java environment other than the ability to add extension jars.

In this instance, I need to be able to call C# code from a Java extension. This is C# code that has previously been used from a purely native context using registration free COM - which works fine. Now I need to be able to make the same code usable from this Java context, but have hit upon the issue that there seems to be no way to control where the DLL should be found. Requiring the DLL to be installed into the JRE/JDK bin directory is clearly not an option, and requiring the DLL to be registered into the GAC would not be ideal.

At present my hope would be that all DLL dependencies would be packaged into the extension jar, and would be loaded when required at runtime (no manual installation step).

I was hoping that I could use the Activation Context API to get this working, and have tested a number of variations on this code, with the DLLs in 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(...);

The manifest contains a single dependentAssembly with the details of the assembly containing the C# class referenced by the call to 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>

Also tried with manifest in this format dumped from the DLL using 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>

The calls to CreateActCtx and ActivateActCtx are successful, but the CoCreateInstance call always fails, returning 0x80070002, unless I put the DLL in C:\Program Files\Java...

Is there any solution out there (other than using the GAC) that would allow a completely unmanaged C++ DLL to load and create an instance of a C# class from a DLL in an arbitrary known location?

.net
dll
com
registration-free-com
activation-context-api
asked on Stack Overflow Aug 14, 2018 by pticawr • edited Aug 15, 2018 by pticawr

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0