使用非托管代码检查.net运行时的存在

时间:2011-05-06 16:53:35

标签: dll unmanaged managed-c++ delay-load

我想创建一个可由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,如果是,怎么做?

1 个答案:

答案 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加载直到以后(在我的情况下,直到我可以从另一个线程完成)。