[ this is getting TLDR...sorry... ]
I work on a huge (mostly) C++/MFC application with hundreds of DLLs; it supports a dynamically-loaded "add in" mechanism via COM, thus add-ins can be developed in .NET by using COM interop. Some limited new functionality is developed in .NET w/o using this "add-in" mechanism (although still dynamically loaded); however, the end user can decide to not use this feature. Thus, .NET might not be loaded at startup.
But, when .NET is loaded, I need to do some .NET-specific initialzation (specifically setting CurrentUICulture to match the native/unmanaged UI).
One solution is to simply punt and do this .NET initialization when the code gets around to loading either the new .NET functionaliy or COM add-ins. Given the nature of this applicaton, it is probably a 95+% solution (most users will be using the new functionality).
But it's not foolproof. Somebody could "readily" add new .NET functionality at any time by building a module with the /clr flag (remember, this is a huge application).
One more robust (and obvious) solution is simply cause .NET to be loaded at startup via C++/CLI. But some of the die-hard C++ developers to whom every byte and clock cycle matter don't want to do this; somewhat understandable as there's no need to set CurrentUICulture unless/until .NET is loaded.
Another possibility I thought of is to hook LoadLibrary
and look for mscorlib. Now I know .NET is about to be loaded for some reason, load it in the normal manner and do the initialization before the other code does anything. But hooking LoadLibrary
(or anything else, for that matter) really isn't something I want to do.
So, is there an easy(ier)/better way to tell if .NET about to be loaded?
Edit: Reed's answer of LockClrVersion is pretty darn close. The only hiccup is that it won't work if you link in a mixed-mode DLL/assembly.
// ClrAboutToLoad.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <MSCorEE.h>
// http://community.bartdesmet.net/blogs/bart/archive/2005/07/22/2882.aspx
FLockClrVersionCallback begin_init, end_init;
STDAPI hostCallback()
{
printf("hostCallback()\n");
// we're in control; notify the shim to grant us the exclusive initialization right
begin_init();
ICLRRuntimeHost *pHost = NULL;
HRESULT hr = CorBindToRuntimeEx(NULL, L"wks", STARTUP_SERVER_GC, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (PVOID*) &pHost);
hr = pHost->Start();
// mission completed; tell the shim we're ready
end_init();
return S_OK;
}
int _tmain(int argc, _TCHAR* argv[])
{
LockClrVersion(&hostCallback, &begin_init, &end_init);
//fnTheDLL();
HMODULE hModule = LoadLibrary(L"TheDLL");
FARPROC fp = GetProcAddress(hModule, "fnTheDLL");
typedef void (*fnTheDLL_t)();
fnTheDLL_t fnTheDLL = reinterpret_cast<fnTheDLL_t>(fp);
fnTheDLL();
FreeLibrary(hModule);
return 0;
}