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

发布于 2024-11-05 09:04:41 字数 1010 浏览 5 评论 0原文

我想创建一个可以由 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,如果可以,如何实现?

I want to create a mixed managed/unmanaged DLL that can be loaded by rundll32, and which checks for the presence of the .Net runtime library before attempting to run any managed code, thusly:

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)

To achieve this, I tried to /DELAYLOAD the CLR (mscoree.dll etc) so that it is only loaded when SomeManagedCode() is called and not before. However, the CLR is still loaded even before RunDllEntryPoint() is called (I can see mscoree.dll in the list of loaded modules). I believe this is because the compiler is linking in code which calls _CorDllMain(), which must force the runtime to load before my own entrypoint is called.

I know there are ways I could repackage this to make it work e.g. split the managed code into a separate DLL, but I'm interested if there's any way to make the above work code in a single DLL.

Is it possible to truly delay-load the CLR dlls, and if so, how?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

○闲身 2024-11-12 09:04:41

是否是 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 加载直到稍后(在我的例子中,直到我可以从不同的线程完成它)。

Could it be the existence of the function call "SomeManagedCode()" in your RunDllEntryPoint that's triggering it? Would it fix things by adding a layer of indirection?

#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");
    }
}

I was in a similar situation, trying to prevent .NET from loading from the wrong thread, and by adding layers of indirection, i.e. never directly call any managed code or managed classes from the native entry point, I was able to push off the .NET loading until later (in my case, until I could do it from a different thread).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文