2

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

4

1 回答 1

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 加载直到稍后(在我的情况下,直到我可以从不同的线程中完成)。

于 2015-06-03T16:18:49.727 回答