AppDomains and Addins


What is an Application Domain (AD)?


An Application Domain is a CLR feature that provides a unit of isolation for an application.  An AD may be thought of as a lighter weight process boundary.  Multiple AppDomains may be created within a host process.  The CLR also verifies that the user code in an App domain is type safe.  An assembly must be loaded into an application domain before it can run (see default domain).  By default, the CLR loads an assembly into the Application Domain containing the code that references it.


Default Domain


When a process that hosts the CLR is created, the CLR automatically creates a default App Domain.  Note that there is one CLR per process.  I will come back to this in future posts when speaking to versioning, Side by Side (SxS), LockCRL version, etc..  The default App Domain remains as long as the host process lives.  The Host code will undoubtly need to live as long as the process, but Add-in’s (Assemblies loaded by the Host) should be isolated from the host code (see isolation).  


Isolation


An isolation boundary provides a level of protection between the Host assembly and the assemblies running in the AD(s).  And of course, an Assembly in one AD is also isolated from an assembly loaded in another AD.  An isolated assembly may not directly access code or resources in another assembly.


The life time of an Add-in(s) may not be as long as the life time of the host process.  The Host should have control over the Add-in’s life time and via isolation the Host has the opportunity to control the temporal nature of Add-in’s.  The host may also load multiple Add-in’s into the same App Domain (clumping) where they have like semantics, such as; shared security context, life times, shared resources, etc..  In the case of ASP.net this is the model.  Imagine a server application that loaded transient code into its process but never had the ability to unload and therefore release resources.  The resources consumed would never be reclaimed.  Can you say, kill PID or reboot periodically please 😉


Unloadability


There is no ability within the CLR to unload an assembly (Why not?) at run time.  The ability to unload an assembly is made possible via unloading an AppDomain and thus the assembly or assemblies within the AppDomain.


Boundaries


As a host, you must be conscience of the remoting boundary in your programming model.  Since you are crossing an AppDomain boundary (just as you would when crossing a process boundary) your objects need to be MarshalByRef (MBRO) and instantiated via System.Runtime.Remoting.  There is a brief discussion on this subject in JasonZ’s blog comments.  Alternatively you could use serialization but you loose the reference semantics as you are making a copy.  For a great write up on value and reference types follow this link


There are versioning considerations you need to understand when communicating between components.  The good news, is that we have the WinFX AddIn model libraries and forth coming guidance on design considerations to help you in this regard.  I will be blogging more on this subject and maybe even co-authoring a book on the subject, if the demand is warranted (hint, hint – tell me if you would find this valuable).


Domain-neutral


Declaring assemblies to have domain-neutral behavior may be accomplished via the runtime hosting interfaces (see the framework SDK CorBindToRuntimeEx).  Loading code that is domain neutral will improve performance on subsequent referencing of the same code in additional AppDomains, because the assembly code pages will be shared across the AppDomains.   


So then the question arises as to why not load everything domain-neutral.  The primary reason is that domain-neutral code may not be unloaded.  So does this conflict with the Add-in model guidance of unloadability and isolation?  No, the majority of the scenarios addressed by the Add-in model would not have Add-in’s loaded in the GAC, nor desired to be shared across AD’s.  Common functionality offered by the hosting application to the Add-in’s, is a likely candidate for domain-neutrality as opposed to Add-in assembly neutrality.  You may wish to reread that last sentence ;-).  These classifications of Host provided assemblies are available to consumers (Add-in’s) for the duration of the Host process.  So there should be no conflict in the Add-in model isolation and unloadability recommendation and domain-neutrality.


In v1.0 and v1.1 native images that Ngen.exe produces cannot be shared (domain-neutrality) across AD’s.  In v2.0, native images that Ngen.exe produces can be shared (domain-neutrality) across AD’s.


AppDomainSetup Properties


There are additional properties to the ones I touch on below,  but I wanted to call out two primary properties of interest.


ApplicationBase


The ApplicationBase is the root directory of the application.  When an AppDomain is created, it inherits the ApplicationBase of the AppDomain creator (the Host in the Add-in model).  When an assembly is loaded from disk, the CLR uses this root as the probing path.  It is very likely that the Add-in will be installed in a different directory than the host application.  In the majority of the cases, the two are installed and uninstalled independently of each other.


ConfigurationFile


The optional configuration file, is an XML file, that has settings for the application.  Most people are familiar with the concept when they think about machine.config.  The configuration file can be used for declaring a startup shim,  versioning rules, etc..  The configuration file will be something along the lines of MyApp.exe.config or MyApp.dll.config.


Security


A host can control policy in two ways.
1. The host can provide evidence when creating the AD.
2. The host can restrict the permissions granted at a policy level.


Simplification


It could be argued that this is a lot of work.  However, the CLR and the framework, already simplify much of this for you.  Of course, as the Host, you must hook up all the various functionality provided via the framework.  The number of Hosts (ISV’s and large application providers) that need to provide this functionality is small in comparison to the number of customizations/applications/Add-in’s that will be written against a Host application.  So the complexity, and thus the burden, is placed on a significantly fewer number of developers.  And to further simplify the lives of ISV’s, which is my current job :-), we have the System.AddIn* offering.


Creation and Assembly loading


Good news


Every good platform provides maximum flexibility.  The CLR and the BCL give you all the pieces parts and runtime functionality you need!
Application Domain’s: AppDomainSetup, AppDomain
Assembly loading: Assembly.Load(AssemblyName), Assembly.LoadFrom(AssemblyName), …
Security: CodeAccessPermission, WebPermission, FileIOPermission, …
Misc: Config file support, Activation, hooking up an entry point, …


Bad news


Getting all this right is hard to do!


More Good news – Our job is to make your life easier!


While we don’t save you money on your car insurance, we do wrap all this up in a nice implementation so you don’t have to.  This is what the System.AddIn.dll is all about.  Or as we often refer to it, the “Loader”.  I will be bloging more on the specific’s of the AddinLoader and AddinExecutor in a future post.

Comments (13)

  1. Ruslan Popov says:

    Because a process can host only one CLR, it is not possible to host add-ins written with different versions of .Net in the same application. For example, you can’t host add-ins written with VS 2003 and VS 2005 in Excel together.

  2. JackG says:

    Good question.  

    Sorry for the delay in responding to your question.  

    We have a new blog Admin tool and I missed your comment.

    The Host (Excel) should determine which version of the CLR is loaded.  

    See LockClrVersion (http://msdn2.microsoft.com/en-us/library/ms230241(VS.80).aspx).

    The Addin’s should not determine which CLR version is loaded.

    If the host does not provide the LockClrVersion it is possible for an Excel COM Addin to load an earlier CLR version and thus lock out other Add-in’s built with later versions of the CLR :(.  

    If Excel loads the latest version of the CLR, VS 2005/CLR v2.0 in this case, then the 2003 Addin will run because the CLR provides backward compatibility between 1.1 and 2.0 framework stacks.

  3. I previously wrote about bi-directional remoting over IPC (see .Net Remoting continued and .Net Remoting

  4. We have gone through some naming changes with WinFX and .Net . And we have gone through a few on the

  5. Frisky says:

    What happens when you add-in is a UI element that needs to be hosted in an UI element in the other AppDomain? So, far, I have not been able to get this to work. The framework does not allow this. (For obvious marshalling reasons.) But, what if I need to load an add-in that supplies a UI to my application, and then later unload it?

    Thanks,

    Frisky

  6. JackG says:

    If I understand your question the answer is that an Add-in loaded into the UI AppDomain can not be unloaded until the UI Host AppDomain is unloaded.

  7. Gary says:

    JackG wrote:

    As a host, you must be conscience of the remoting boundary in your programming model.  …crossing an AppDomain boundary

    I will be blogging more on this subject and maybe even co-authoring a book on the subject, if the demand is warranted  

    (hint, hint – tell me if you would find this valuable).

    Guidance for ISVs on this topic would be very helpful.

  8. JackG says:

    Hi Gary,

    At a high level I would *highly* encourage Hosts to build thier OM with a design supporting isolation via an AD (or OOP). Now that we have the CLR implementation of the Add-In model in v3.5 of the BCL (Orcas), I would recommend building on the library and designing your OM on the design pattern of the pipeline.

    I have published more on the subject and wrt the types that may flow accross the boundary, you can read my post on Contract Constraints (http://blogs.msdn.com/jackg/archive/2007/02/27/extensibility-add-in-guidance.aspx). As far as the book goes – it is unlikely. Mahalo, JackG

  9. We just posted a solution to consider for the F.A.Q. of how to enable isolatable WinForms applications.

  10. We just posted a solution to consider for the F.A.Q. of how to enable isolatable WinForms applications

  11. WPFNET says:

    Hi,

    Is it possible to unload an Add-in which contains a Winforms UserControl. I tried with the example given at

    http://softwaregreenhouses.com/blog/2008/01/13/part-ii-windows-controls-extensibility-with-net-35-clr-add-ins-using-wpf-and-crossbow/trackback/

    When I unloaded the add-in’s AppDomain, the main application is closed silently. Please correct me if something is wrong here.

    Thanks

  12. JackG says:

    WPFNet, I didn’t look into the sample but I would suspect an unhandled exception on a user thread in the AddIn may be causing the Host to be torn down. It should be fine to unload the AddIn AppDomain. – JackG