Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading assemblies from memory when hosting the CLR in unmanaged programs

I managed to host the CLR in an unmanaged program thanks to rich documentation. However when hosting the CLR, it appears that one is restricted to load assemblies from harddrive - When running a managed application one can load assemblies from memory by calling Assembly.Load() though.

Is there any way to execute an assembly in the hosted CLR from memory? Like:

  1. Write managed assembly to memory
  2. Initiate CLR
  3. Start CLR
  4. Execute managed assembly from memory
  5. Wait for the managed assembly to return
  6. Stop CLR

I've searched the web and MSDN for hours but couldn't find a solution to this problem! A workaround I came up with would involve yet another assembly that calls Assembly.Load() - However I'm afraid that this may be overkill.

Thanks in advance for any hints or tips!

like image 380
Bigmo Avatar asked Mar 15 '23 12:03

Bigmo


1 Answers

I suggest you start from this sample here: C++ app hosts CLR 4 and invokes .NET assembly (CppHostCLR) that seems to do almost what you need. The only missing part is it's not loading the assembly from memory, but uses a file instead.

So what you need to do is just replace the following lines (in RuntimeHostV4.cpp):

// Load the .NET assembly. 
wprintf(L"Load the assembly %s\n", pszAssemblyName); 
hr = spDefaultAppDomain->Load_2(bstrAssemblyName, &spAssembly); 
if (FAILED(hr)) 
{ 
    wprintf(L"Failed to load the assembly w/hr 0x%08lx\n", hr); 
    goto Cleanup; 
} 

by the following lines that use this method instead: _AppDomain.Load Method (Byte[])

// let's suppose I have a LPBYTE (pointer to byte array) and an ULONG (int32) value
// that describe the buffer that contains an assembly bytes.
LPBYTE buffer = <my buffer>;
ULONG size = <my buffer size>;

// let's create an OLEAUT's SAFEARRAY of BYTEs and copy the buffer into it
// TODO: add some error checking here (mostly for out of memory errors)
SAFEARRAYBOUND bounds = { size, 0 };
SAFEARRAY *psa = SafeArrayCreate(VT_UI1, 1, &bounds);
void* data;
SafeArrayAccessData(psa, &data);
CopyMemory(data, buffer, size);
SafeArrayUnaccessData(psa);

hr = spDefaultAppDomain->Load_3(psa, &spAssembly);
if (FAILED(hr))
{
    wprintf(L"Failed to load the assembly w/hr 0x%08lx\n", hr);
    goto Cleanup;
}
SafeArrayDestroy(psa); // don't forget to destroy
like image 66
Simon Mourier Avatar answered Mar 18 '23 07:03

Simon Mourier