.NET Framework предоставляет большое количество способов взаимодействия управляемого и неуправляемого кода, включая COM Interop и P/Invoke. Существует много материалов, посвящённых данному вопросу. Однако о такой возможности, как запуск CRL в неуправляемом процессе посредством CLR Hosting API, написано сравнительно немного. Запуск среды выполнения в неуправляемом приложении может быть полезен, в следующих случаях:
Например, хостинг CLR используется в приложениях Microsoft Office (управляемые надстройки) и Microsoft SQL Server (CLR Stored Procedures).
В первой версия CLR Hosting API для взаимодействия со средой выполнения используется интерфейс ICorRuntimeHost, который можно получить при помощи статических функций CorBindTo* (например, CorBindToRuntie) библиотеки MSCorEE.dll.
В этой версии многие аспекты хостинга CLR перенесены из неуправляемого в управляемый код (программист может управлять хостингом при помощи наследника класса AppDomainManager). Появился новый интерфейс ICLRRuntimeHost.
Предыдущие версии CLR Hosting API имели важное ограничение – было невозможно запустить более одной версии CLR в одном процессе. Это означает, что если есть две надстройки, написанные с использованием разных версий CLR, то, как минимум, одну из них придется запускать не под той версией исполняющей среды, для которой она разрабатывалась. Начиная с .NET Framework 4.0 появилась возможность загрузить нескольких версий CLR в одном процессе, при этом одновременно смогут работать сколько угодно версий исполняющей среды (начиная c 4.0) и одна из старых версий (CLR1.1 или CLR2.0). Старые статические функции (CorBindTo*) объявлены устаревшими, вместо них предлагается использовать функцию CLRCreateInstance и методы интерфейсов ICLRMetaHost и ICLRRuntimeInfo.
В CLR Hosting API можно выделить две большие группы интерфейсов:
При помощи этих интерфейсов можно контролировать такие аспекты работы CLR, как:
Для всех источников, кроме первого, есть переводы на русский язык.
- поддержка расширений, написанных на управляемых языках;
- создание навесных защит для управляемых приложений;
- управление работой CLR;
- сложные случаи отладки;
- постепенный перевод большого неуправляемого приложения на .NET.
Например, хостинг CLR используется в приложениях Microsoft Office (управляемые надстройки) и Microsoft SQL Server (CLR Stored Procedures).
Развитие CLR Hosting API
.NET Framework 1.x
В первой версия CLR Hosting API для взаимодействия со средой выполнения используется интерфейс ICorRuntimeHost, который можно получить при помощи статических функций CorBindTo* (например, CorBindToRuntie) библиотеки MSCorEE.dll.
.NET Framework 2.0
В этой версии многие аспекты хостинга CLR перенесены из неуправляемого в управляемый код (программист может управлять хостингом при помощи наследника класса AppDomainManager). Появился новый интерфейс ICLRRuntimeHost.
.NET Framework 4.0 и In-Process Side-by-Side
Предыдущие версии CLR Hosting API имели важное ограничение – было невозможно запустить более одной версии CLR в одном процессе. Это означает, что если есть две надстройки, написанные с использованием разных версий CLR, то, как минимум, одну из них придется запускать не под той версией исполняющей среды, для которой она разрабатывалась. Начиная с .NET Framework 4.0 появилась возможность загрузить нескольких версий CLR в одном процессе, при этом одновременно смогут работать сколько угодно версий исполняющей среды (начиная c 4.0) и одна из старых версий (CLR1.1 или CLR2.0). Старые статические функции (CorBindTo*) объявлены устаревшими, вместо них предлагается использовать функцию CLRCreateInstance и методы интерфейсов ICLRMetaHost и ICLRRuntimeInfo.
Управление работой CLR
В CLR Hosting API можно выделить две большие группы интерфейсов:
- интерфейсы хост-диспетчеров (host managers), их имена начинаются с префикса IHost, они реализуются на стороне неуправляемого приложения и вызываются CLR;
- интерфейсы диспетчеров CLR (CLR managers), которые реализуются CLR и вызываются на стороне неуправляемого приложения.
При помощи этих интерфейсов можно контролировать такие аспекты работы CLR, как:
- работа с памятью (ICLRGCManager, ICLRMemoryNotificationCallback, IHostGCManager, IHostMAlloc, IHostMemoryManager);
- работа с потоками(ICLRTaskManager, IHostTaskManager, IHostThreadPoolManger);
- синхронизация потоков(ICLRSyncManager, IHostCrst, IHostSyncManager, IHostManualEvent);
- загрузка сборок (ICLRAssemblyIdentityManager, IHostAssemblyStore, IHostAssemblyManager);
- настройка CLR (ICLRControl, ICLRPolicyManager, ICLRDebugManager).
Пример использования CLR Hosting API
#include <metahost.h>
#pragma comment(lib, "mscoree.lib")
int wmain( int argc, wchar_t** argv )
{
ICLRMetaHost *pMetaHost = nullptr;
ICLRRuntimeInfo *pCLRRuntimeInfo = nullptr;
ICLRRuntimeHost *pCLRRuntimeHost = nullptr;
__try
{
HRESULT hr;
// Получаем среду выполнения
hr = CLRCreateInstance( CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost );
if ( FAILED(hr) ) return -1;
hr = pMetaHost->GetRuntime( L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID*)&pCLRRuntimeInfo );
BOOL bCLRIsLoadable;
hr = pCLRRuntimeInfo->IsLoadable( &bCLRIsLoadable );
if ( FAILED( hr ) ) return -1;
if ( ! bCLRIsLoadable ) return -1;
hr = pCLRRuntimeInfo->GetInterface( CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&pCLRRuntimeHost );
if ( FAILED(hr) ) return -1;
// Запускаем CLR
hr = pCLRRuntimeHost->Start();
if ( FAILED(hr) ) return -1;
// Загружаем сборку и вызываем в ней метод
DWORD nRet;
hr = pCLRRuntimeHost->ExecuteInDefaultAppDomain( L"TestLib.dll", L"TestLib.Foo", L"Bar", L"", &nRet );
if ( FAILED(hr) ) return -1;
}
__finally
{
// Освобождаем ресурсы
if ( pCLRRuntimeHost ) { pCLRRuntimeHost->Release(); pCLRRuntimeHost = nullptr; }
if ( pCLRRuntimeInfo ) { pCLRRuntimeInfo->Release(); pCLRRuntimeInfo = nullptr; }
if ( pMetaHost ) { pMetaHost->Release(); pMetaHost = nullptr; }
}
return 0;
}
Литература
- Steven Pratschner, Customizing the Microsoft .NET Framework Common Language Runtime
- Jeffrey Richter, CLR Via C#
- CLR Inside out: CLR Hosting APIs, MSDN Magazine, August 2006
- CLR Inside out: In-Process Side-by-Side, MSDN Magazine, December 2009
Для всех источников, кроме первого, есть переводы на русский язык.