Использование неуправляемого кода для проверки наличия среды выполнения .net

#dll #unmanaged #managed-c #delay-load

#dll #неуправляемый #управляемый-c #задержка загрузки

Вопрос:

Я хочу создать смешанную управляемую / неуправляемую DLL, которая может быть загружена rundll32 и которая проверяет наличие .Библиотека Net runtime перед попыткой запуска любого управляемого кода, таким образом:

 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(), а не раньше. Однако среда CLR все еще загружается даже до вызова RunDllEntryPoint() (я вижу mscoree.dll в списке загруженных модулей). Я полагаю, это потому, что компилятор ссылается в коде, который вызывает _CorDllMain(), который должен принудительно загрузить среду выполнения до вызова моей собственной точки входа.

Я знаю, что есть способы, которыми я мог бы переупаковать это, чтобы заставить его работать, например, разделить управляемый код на отдельную DLL, но мне интересно, есть ли какой-либо способ заставить приведенный выше рабочий код работать в одной DLL.

Возможно ли действительно отложить загрузку библиотек CLR DLL, и если да, то как?

Ответ №1:

Может ли это быть вызвано существованием вызова функции «SomeManagedCode()» в вашей RunDllEntryPoint, которая запускает это? Исправит ли это ситуацию, добавив слой косвенности?

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

Я был в аналогичной ситуации, пытаясь предотвратить .СЕТЬ от загрузки из неправильного потока и путем добавления уровней косвенности, т. е. никогда напрямую не вызывать какой-либо управляемый код или управляемые классы из собственной точки входа, я смог отказаться от .Загрузка СЕТИ отложена на потом (в моем случае, пока я не смогу сделать это из другого потока).