I’m working on an older FoxPro application that’s using .NET Interop and this app loads its own copy of the .NET runtime through some of our own tools (wwDotNetBridge). This all works fine and it’s fairly straightforward to load and host the runtime and then make calls against it. I’m writing this up for myself mostly because I’ve been bitten by these issues repeatedly and spend 15 minutes each
However, things get tricky when calling specific versions of the .NET runtime since .NET 4.0 has shipped. Basically we need to be able to support both .NET 2.0 and 4.0 and we’re currently doing it with the same assembly – a .NET 2.0 assembly that is the AppDomain entry point. This works as .NET 4.0 can easily host .NET 2.0 assemblies and the functionality in the 2.0 assembly provides all the features we need to call .NET 4.0 assemblies via Reflection.
In wwDotnetBridge we provide a load flag that allows specification of the runtime version to use. Something like this:
do wwDotNetBridge
LOCAL loBridge as wwDotNetBridge
loBridge = CreateObject("wwDotNetBridge","v4.0.30319")
and this works just fine in most cases. If I specify V4 internally that gets fixed up to a whole version number like “v4.0.30319” which is then actually used to host the .NET runtime. Specifically the ClrVersion setting is handled in this Win32 DLL code that handles loading the runtime for me:
/// Starts up the CLR and creates a Default AppDomain
DWORD WINAPI ClrLoad(char *ErrorMessage, DWORD *dwErrorSize)
{
if (spDefAppDomain)
return 1;
//Retrieve a pointer to the ICorRuntimeHost interface
HRESULT hr = CorBindToRuntimeEx(
ClrVersion, //Retrieve latest version by default
L"wks", //Request a WorkStation build of the CLR
STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN | STARTUP_CONCURRENT_GC,
CLSID_CorRuntimeHost,
IID_ICorRuntimeHost,
(void**)&spRuntimeHost
);
if (FAILED(hr))
{
*dwErrorSize = SetError(hr,ErrorMessage);
Read more: Rick Strahls web log
However, things get tricky when calling specific versions of the .NET runtime since .NET 4.0 has shipped. Basically we need to be able to support both .NET 2.0 and 4.0 and we’re currently doing it with the same assembly – a .NET 2.0 assembly that is the AppDomain entry point. This works as .NET 4.0 can easily host .NET 2.0 assemblies and the functionality in the 2.0 assembly provides all the features we need to call .NET 4.0 assemblies via Reflection.
In wwDotnetBridge we provide a load flag that allows specification of the runtime version to use. Something like this:
do wwDotNetBridge
LOCAL loBridge as wwDotNetBridge
loBridge = CreateObject("wwDotNetBridge","v4.0.30319")
and this works just fine in most cases. If I specify V4 internally that gets fixed up to a whole version number like “v4.0.30319” which is then actually used to host the .NET runtime. Specifically the ClrVersion setting is handled in this Win32 DLL code that handles loading the runtime for me:
/// Starts up the CLR and creates a Default AppDomain
DWORD WINAPI ClrLoad(char *ErrorMessage, DWORD *dwErrorSize)
{
if (spDefAppDomain)
return 1;
//Retrieve a pointer to the ICorRuntimeHost interface
HRESULT hr = CorBindToRuntimeEx(
ClrVersion, //Retrieve latest version by default
L"wks", //Request a WorkStation build of the CLR
STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN | STARTUP_CONCURRENT_GC,
CLSID_CorRuntimeHost,
IID_ICorRuntimeHost,
(void**)&spRuntimeHost
);
if (FAILED(hr))
{
*dwErrorSize = SetError(hr,ErrorMessage);
Read more: Rick Strahls web log