Setting up an AppDomainManager

When I first talked about AppDomainManagers, I mentioned that there were three ways to tell the CLR that you’d like to use the managed hosting infrastructure:

  1. The unmanaged hosting API


  3. A set of registry keys

Of these three, which one should you pick?  Obviously the unmanaged hosting API is only available to you if you’re willing to have an unmanaged component of your application.  Of course if you do have an unmanaged component, and you want to have communication back and forth between the two halves, using this API and setting AppDomainManagerInitializationOptions.RegisterWithHost in your InitializeNewDomain method is a great way to get that setup.

If you’re sticking with a purely managed application, that leaves you with the other two options.  Given the choice between the two, you should almost always choose the environment variables over the registry keys.

The problem with the registry keys is that there’s only one set of them for every application running under your user profile.  This means that if your application chooses to set these keys it creates several different types of problems.  First, every managed application that starts after the keys are set will use the AppDomainManager (unless they specify their own using one of the other two methods).  Since those applications have not been tested running with your AppDomainManager, and AppDomainManagers are generally used to modify the behavior of the CLR, this will likely lead to all kinds of unpredictable behavior which will be very difficult to trace back to the source.

Even if your AppDomainManager is relatively inert and does not affect the other applications in any way, the fact that there is only one set of registry keys creates another problem.  If two applications decide that they’re going to setup their AppDomainManager using these keys during setup, you have an obvious problem.  However, even if two applications provide a shim program to set the keys and then kick off their real code, you still have a race condition:

  1. Application A sets the registry key for AppDomainManager A

  2. Application B sets the registry key for AppDomainManager B

  3. Application A starts with AppDomainManager B

  4. Application B starts with AppDomainManager B

The world is great for Application B, however Application A probably is not going to run very well at all since the AppDomainManager it was depending upon is not running in its process.

On the other hand, environment variables are inherited from the parent process, and can be modified by each child. Since different processes can have separate environment blocks with the same environment variables having different values, you avoid all the race conditions above.

Incidentally, one question that comes up relatively often is why didn’t we enable an application to specify its AppDomainManager in the .exe.config file?  The reason is security — every managed .exe can supply an .exe.config file.  Since AppDomainManagers are so powerful, we didn’t want to expose the ability to specify one to untrusted code.  Instead, the only ways to set one up involve running managed code, having write access to the environment, or having write access to the registry.  Since these are all trusted operations, fencing off the AppDomainManager to only applications that can perform them reduces the surface area for attack on this feature.

Comments (5)

  1. MichaelM says:

    Thanks for the direction. I posted a question at 7:00 and got a whole blog post an hour and a half later. That’s a better turnaround response than I often get in my own company when I have dev questions.

  2. If one can change the .exe.config file, he can also set environment variables, can’t he?

    Anyway, I can think of another way setting the domain manager: how about an assembly attribute, e.g.

    [assembly: AppDomainManager(typeof(MyAppDomainManager))]

    The runtime could look up such an attribute before starting the application.

  3. The problem isn’t code modifying somebody else’s .exe.config file, it’s malicious code providing its own .exe.config. For instance, you don’t want a partial trust MaliciousApp.exe running with MaliciousApp.exe.config which specifies an AppDomainManager — by allowing that the malicious app could easily elevate its permissions above what you’d like.

    The same is true withe the custom attributes — we don’t want MaliciousApp to supply the AppDomainManagerAttribute.

    It’s possible that we might look at enabling this in a future release for fully trusted code, but for Whidbey it was too much of an attack surface to expose.


  4. Last time I mentioned that when using pure managed code to setup an AppDomainManager, you should prefer…

  5. Leon says:

    Hi, we have a new interface in 2.0 to control the CLR: ICLRRuntimeHost. Earlier samples for CLR hosting used ICLRRuntimeHost::GetDefaultDomain/etc, but in beta 2 any AppDomain creation/manipulation is gone from that interface. How should one GetDefaultDomain/CreateDomain in .NET 2.0? I can’t get both ICLRRuntimeHost and ICorRuntimeHost. Thanks for any pointers