#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");
}
}
Я был в аналогичной ситуации, пытаясь предотвратить .СЕТЬ от загрузки из неправильного потока и путем добавления уровней косвенности, т. е. никогда напрямую не вызывать какой-либо управляемый код или управляемые классы из собственной точки входа, я смог отказаться от .Загрузка СЕТИ отложена на потом (в моем случае, пока я не смогу сделать это из другого потока).