I'm currently playing with the
ICLRRuntimeHost interface. This lets you load the CLR into your unmanaged process and gives you a remarkable amount of control over how the CLR that you're hosting operates. Unfortunately it's got some dubious design issues... Firstly you can only have one instance of the CLR hosted in your process; that's just about fair enough, I guess, but I'd still be curious to know why... Secondly, if you try and load a second or subsequent instance you'll get
S_FALSE returned from your call to
CorBindToRuntimeEx()... The error isn't currently documented in the online docs for the function... Interestingly, you get the same error whether you've requested the same version of the CLR with the same configuration settings or if you've requested a completely different version, so, it doesn't mean "you've already loaded the CLR like this" it means "you've already loaded a version of the CLR somehow". Again this isn't likely to be much of a problem as you can't ever unload the CLR so the first one that you load is the only one you can ever load...
Then there's the
Stop() method on
ICLRRuntimeHost... The docs for this are "interesting"; online we have "pre-release" docs which say: "This method does not release resources to the host, unload application domains, or destroy threads. You must terminate the process to release these resources.", whilst VS 2005 SP1's help says "Do not call this method. The host cannot unload the runtime from a process." which is amusing at best. What's more, if you DO call it then it seems to return
E_UNEXPECTED if you call it before starting the CLR (which is probably what you'd expect) and it seems to work like a 'reference counted' "Stop" (you can call it as many times as you've called
Start() and all except the last call returns
S_FALSE and the last call returns
S_OK), which, again, is pretty much what you might expect... Unfortunately, once it's returned
S_OK the CLR in your process is screwed, not only is it stopped (probably not that cleanly if the docs are anything to go by) but you can't ever start another CLR in your process; though calling
CorBindToRuntimeEx() still returns
Of course none of this is really a "problem" if you use the code in the way that some of the docs that you might come across suggest that you should do but I do find myself wondering "Why was v2.0 of the .Net Common Language Runtime allowed to go out the door with this half arsed implementation of a new interface?" After all, if you use the 'backwards compatibility' excuse then, well, even if you were relying on using the functionality during the beta phase, you shouldn't be calling
Stop() anymore so surely it's better to break any code that was using it rather than leaving it "working"? Or, if you really couldn't change the interface at that late a date then surely a method that's documented as "don't call this" should be a no-op inside and just return
S_FALSE the whole time and do nothing?
I'm also a bit concerned about the fact that you can't shut the CLR down cleanly once it's started... I'm a bit of a fan of being able to start and stop my code, no matter how complex it is. The fact that it looks like the original design allowed for stopping the CLR and the actual implementation can't do that is a little worrying...
Of course this annoys me most simply because it makes testing any code that happens to host the CLR a much harder job. As is often the way, the implementation flaw in Microsoft's code leaks out and becomes a flaw in all the code that uses it... I can't test my code to load and host the CLR with various different, valid and invalid, options without starting a different process for each test... Bleugh...I think I need a new category of blog postings, "Rants", though perhaps most of my postings could be categorised that way...