我想创建一个可由rundll32加载的混合托管/非托管DLL,并在尝试运行任何托管代码之前检查是否存在.Net运行时库,因此:
using namespace System;
void SomeManagedCode()
{
Diagnostics::Debug::WriteLine("Hello managed code!");
}
#pragma managed(push,off)
bool isRuntimeInstalled()
{
// check for runtime using some *unmanaged* code
return true;
}
extern "C" __declspec(dllexport) void _stdcall RunDllEntryPoint(
HWND hWnd, HINSTANCE hInst, LPSTR lpszCmdLine, int nCmdShow)
{
if (isRuntimeInstalled())
{
SomeManagedCode();
}
else
{
OutputDebugString(L".net framework not installed");
}
}
#pragma managed(pop)
为了实现这一点,我尝试/DELAYLOAD
CLR(mscoree.dll等),以便只在调用SomeManagedCode()时才加载它,而不是之前。但是,即使在调用RunDllEntryPoint()之前仍然加载CLR(我可以在加载的模块列表中看到mscoree.dll)。我相信这是因为编译器在调用_CorDllMain()的代码中进行链接,该代码必须在调用我自己的入口点之前强制运行时加载。
我知道有一些方法可以重新包装它以使其工作,例如将托管代码拆分为一个单独的DLL,但我很感兴趣,如果有任何方法可以在单个DLL中生成上述工作代码。
是否有可能真正延迟加载CLR dll,如果是,怎么做?
答案 0 :(得分:0)
可能是RunDllEntryPoint中是否存在触发它的函数调用“SomeManagedCode()”?它会通过添加一个间接层来解决问题吗?
#pragma managed
void SomeManagedCode()
{
Diagnostics::Debug::WriteLine("Hello managed code!");
}
#pragma unmanaged
void CallSomeManagedCode()
{
SomeManagedCode();
}
extern "C" __declspec(dllexport) void _stdcall RunDllEntryPoint(
HWND hWnd, HINSTANCE hInst, LPSTR lpszCmdLine, int nCmdShow)
{
if (isRuntimeInstalled())
{
CallSomeManagedCode();
}
else
{
OutputDebugString(L".net framework not installed");
}
}
我处于类似情况,试图阻止.NET从错误的线程加载,并通过添加间接层,即从不直接从本机入口点调用任何托管代码或托管类,我能够推送关闭.NET加载直到以后(在我的情况下,直到我可以从另一个线程完成)。