Behind the Scenes: Activation [Pete Sheill]

Let’s discuss the specifics of the construction of the add-in, the isolation boundary and the pipeline in the add-in model – i.e. activation.  I’ll be referring to the discovery and activation as discussed here and the segments of the add-in pipeline as discussed here.  Let’s say you have discovered a single token for an add-in, and you have decided to activate it.  To isolate the add-in from the host you chose to run it in its own new appdomain.  What happens next when you call one of the Activate() methods on the add-in token?  Let’s enumerate all of the steps that the system takes:


1.      The appdomain is created with the permissions that you specified in the call to Activate(). 

2.      The add-in assembly is loaded into that appdomain through a call to Assembly.LoadFrom(), passing in the location of the assembly.  The add-in type will not be loaded in the host’s appdomain.  In other uses this call can cause loader context issues if not used carefully, but we’ve taken steps to avoid them here.  In fact, this method was created specifically to support add-in scenarios. 

3.      We use reflection to call the no-argument constructor for the add-in to create an instance in that appdomain.  Naturally, since the add-in derives from the AddInBase class that is deployed in the AddInView assembly, this action causes the loader to load that assembly.  At this point we have an instance of the add-in running in its own appdomain.  Now we need to connect it to the host. 

4.      An instance of the AddInSideAdapter is constructed, passing in the add-in (typed as the add-in base) as the only argument to the constructor.  (This adapter implements a Contract interface and derives from MarshalByRefObject through the intermediate ContractBase class.  Therefore it can appear to live in both the host’s and the add-in’s appdomain—any calls to it from the host’s domain are proxied and executed in the add-in’s appdomain.) 

5.      The activation code passes the add-in adapter back to the host’s appdomain typed as the Contract that it implements. 

6.      An instance of the HostSideAdapter is constructed in the host’s appdomain, with the AddInSideAdapter being passed in as its only argument.  The exact HostSideAdapter type is determined by examining the add-in token.  This adapter derives from (or implements) the HostViewOfAddin that the host compiled against. 

7.      The activation code returns the host-side adapter to the host, typed as the HostViewOfAddin. 


The host will sometimes do further initialization of the add-in through a separate call, passing in any needed arguments.  Then it is up to the host and add-in to communicate as needed.  Activation has completed. 


Do the adapters need to be public?  Actually, no.  Though the normal rules of visibility would suggest that they would need to be public in order to be created and used by the activation code, the rules don’t apply in this case.  That’s because we use reflection to invoke the constructor, and given enough permission, reflection can invoke non-public constructors.  We didn’t want the adapters to need to be public because they exist as an implementation detail, not things to be documented and supported in themselves.


When the HostSideAdapter is constructed with a reference to the AddInSideAdapter, it does something right away that we wouldn’t need to do if all the objects were in the same appdomain.  It needs to call the AcquireLifetimeToken() member, specified in the IContract interface, of that adapter.  That is part of another big topic, lifetime management.  We’ll discuss that in another post.


This is one way to activate an addin in this model.  There are also some other different ways you could activate the same addin.  You could choose to activate it in the same appdomain as the host.  You could also choose to activate it in an entirely separate process, if isolation matters above all else.  We’ll explore those options more in later posts.

Comments (18)

  1. claudio says:


    I just tried multiprocess activation and it works fine.

    I was wondering if you are going to support Async calls to Addins, in order to avoid to block the calling application.



  2. Burton says:

    with in-process addins, will this architecture support addins, plugging in or providing UI elements?  what are the mechanics?

    i know with the current framework there’s issues with serializing/marshalling controls.

  3. JJB says:

    This isn’t directed at Pete per say but the whole add-in team:

    I’m working on a fairly large project that makes heavy use of add-ins. I was excited to find out about this project but now that I’ve tried it out and written some code using this model I have to say I’m really disappointed.

    1. For starters do you think you could add a few more wrappers and layers in here somewhere? I don’t think it’s complex enough yet. Seriously! You have to be kidding! Not counting the host and add-in themselves there’s 5 layers that are nothing but wrappers. Plus the marshalbyref proxy’s you must be using internally somewhere. And that’s 5 layers for every class. myRetObj = plugin.Initialize(MyhostObj);  There’s at least 15 layers of cruft in that single call.

    2. It seems that you’ve taken the simple concept of an interface and tossed it out the window. Instead of declaring an interface once and using it where needed you have to define the exact same abstract class twice (host view & addin view). Yeah, you put different attributes on each. So what! it’s still the same damn class defined twice. Hardly the model of efficiency and makes future maintainability a big PIA!

    3. Why force the use of adapters? If V2 of the plugin API doesn’t exist yet, what’s the point?   It looks like your using what should be a simple versioning tool to do your lifetime management. That doesn’t seem to make a lot of sense to me.

    4. Why do the addin side adapter and addin view have to be in separate dll’s? And why are the paths hard coded in the .net framework? It’s not even consistent. Why can’t I put everything in one folder named Non-Value-Added-Addin-Stuff?

    Sorry for the long rant but this has really frustrated me 🙂

  4. Dhaval Patel says:

    I spoke to Jesse [Kaplan] on multiple occasions and thought it would be better to post this topic here instead of emailing directly. Jesse mentioned that there would be provisions this time around for developers to load an executable (plugin) in a new app domain along with its respective app.config file! I was wondering if any one of you folsk can throw some more light on this issue (an example would give me immense pleasure!). Also, if this feature is provided, what would be the consequences when someone loads multiple plugins – specifically, will the plugins depend on the host (not good) for config info, or each plugin will be allowed its plugin file (very good!). Also, if each plugin can have its own config file, I am sure there will be ways to detect that plugin’s config file?


  5. Atul Gupta says:

    Does this Add-In API set allow EXEs to also be loaded and communicted with or does it work only with DLLs.. essentially the question is can the AddIn have its own UI that it will show in the AppDomain?

  6. Garry Trinder says:

    Atul, I don’t believe we have any issues with Add-in’s as exe’s.  We won’t call Main() however.  Add-in’s may have UI. – Jack

  7. Garry Trinder says:

    Dhaval, A quick look at the code looks like we support Add-In config files.  Examples of config files may be found on here ( – JackG

  8. noslenytram says:

    Just some comments on JJB’s rant:

    While the current add-in model is particular about the placement of separate dll’s for adapter and contract layers, you can have a common interface that both the add-in and host view use.  

    And after the initial add-in pipeline has been established, you have a lot more flexibility as to where you can store subsequent adapters.  I’m currently using a single adapter dll that both the host and add-in adapter dll’s reference.  

    I find everything needs a contract in the contract dll, mostly because things need to be neutered to either base CLR types or other contracts.

    The pay-off is not in today’s code, but in tomorrow’s code.  Also, being beta we have to hand code everything, whereas I expect we may see some code gen tools sooner or later.

  9. Garry Trinder says:

    Thanks for the feedback, JJB.

    It’s hard to argue with the fact that we have a complex (more on this later) model due in part to addressing a breadth of issues; Discovery, Activation, Isolation, Versioning, Unloadability, Sandboxing, Lifetime management.

    Our primary goal was to ensure Add-In developers (Host consumers and service providers) would not be burdened by the complexity of the model.  The Add-In author experience is very simple and their “view” (i.e., Façade) is a natural .Net strongly typed experience.

    We also wanted to ensure the Host application developer experience was not complicated by the model or the complexities of versioning (e.g., Interface casting throughout the code).

    We recognize the complexity for the Object Model developer (true that all three developers may be the same person).  We continue to look into enhancing this experience in terms of development and performance.  Tooling would also go a long way in simplifying the experience.  We continue to work on all of the above.  Stay tuned for some new functionality in Orcas Beta2.

    The Host and Add-In views are not always the same interface.  In fact, the abstraction “layers” and the ability to adapt between “interface” views are core to the offering.  Check out the second MSDN article sample code.

    It is true that demanding Adapters for a v1 implementation when there may be no v2 (yet) adds overhead.  However, if you design for versioning and isolation in v1, you can attain both in v.Next+.  If however, you do not design for this functionality in v1, you can’t retrofit your model for the past.  Adapters provide the ability to have logic/functionality version over version that enables greater flexibility beyond things like servicing.  They also give you the ability to do things like ageing out your legacy OM, without changing the consumers view of your model.

    Lifetime management – As the model supports cross AppDomain communications we need an ability to handle the lifetime of a reference across AppDomain boundaries.  The CLR does not support GC across distributed components and the Adapters give us the ability to merge the ref counting and GC semantics.  

    A purely interfaced based model (i.e., Non-Adaptive) has a number of issues we will blog about in the future.  Many of us (including our customers)  have personal experience with a purely interface based model and the long and short of it is that over time this model has many short comings.  In short, there are versioning constraints placed upon Interfaces vs. Abstract base classes, having to cast up/down and the bleeding of this logic into both the Host and/or Add-in programming models is less than desirable in particular when you reach v2+.

    I will post a blog entry forthcoming on Assembly package considerations and flexibilities therein.  The reason the views are in separate assemblies is due to the static reference from the Host/Add-in to each and the fact that type versions are Assembly based in the CLR.

    The paths are relative to the user defined Pipeline root path.  Btw, the Pipeline path may be different than the Add-in(s) path.  We could have an overload to Discovery in order to provide a more flexible path convention for Pipeline segments, but I’m not sure that is any more desirable than the current “hard coded” implementation.

    Thanks for the feedback. – JackG

  10. Pete Sheill says:


    We do support invoking addin methods asynchronously.  For the methods that need to be invoked that way, create a delegate in the HostViewOfAddIn and call BeginInvoke on that delegate.  Note that care should be taken to properly handle errors, including exceptions, since you will no longer be on the main thread’s call stack.    

    Here are more details on this:


  11. Garry Trinder says:

    Regarding support for UI elements – Here you go!

    • JackG
  12. David Piepgrass says:

    Hi, I have been reading about this new add-in system with some interest, but I’m concerned about whether it can meet my needs.

    I’m developing a nongraphical "workhorse" application (a highly extensible compiler, actually) that will rely heavily on an add-in system because it is intended that almost any piece of functionality can be replaced, hooked-into, or supplemented by add-ins. Much like SharpDevelop, my idea is that most of the core features will actually be located in add-ins, and other "2nd-tier" add-ins will hook into the main add-ins. Furthermore, add-ins should be able to invent their own interfaces to communicate with each other and with "3rd tier" or "4th tier" addins.  In short, the interconnections between add-ins are be complicated, arbitrary, and extensible.

    It also needs to be high-performance. I have the impression there’s a big penalty for crossing AppDomain boundaries, but this application doesn’t need AppDomains at all (or if it does, it will only need two: a higher-security domain where all the add-ins run, and a low-security domain which will have full access to the file system.)

    When one add-in calls another, there should be no more overhead than a normal method call through an interface (unless an adapter is required). I’d like to make sure that no adapter classes are required if no adapters are needed (i.e. when the interface exactly matches the implementation, as will be the case most of the time.)

    Can the new Add-in system support this scenario?

  13. Garry Trinder says:

    Hello David,

    Please take a look at our recent post on new features in beta2 and I think you’ll find something that fits your need:

    There is a new feature called DirectConnect which ensures that when the feature is enabled we avoid activating the pipeline in the cases where the host and add-in use the same interface and are in the same AppDomain. This allows you to avoid the extra overhead of the pipeline when you don’t need it.

    We still encourage you to take a look at AppDomain isolation and verify that the costs are too expensive before you rule it out as you may find that it is acceptable. But there are definitely cases where the need for performance trumps the needs for isolation which is why we added the above feature.

  14. David Piepgrass says:

    Thanks for the answer. I should add that my framework will provide a number of generic interfaces and classes, as well as other things such as IEnumerable<> or IList<> of other interfaces and non-serializable classes, which go against the "Restrictions on Contracts". Can the Add-in framework disregard all these restrictions when staying within one AppDomain? After all, all I really need is to keep track of what add-in assemblies and classes are available, and to load the assemblies and instantiate the classes on-demand from tokens. Since it is a compiler project, the process itself is short-lived and the inability to unload DLLs is not a problem.

    I see that isolation is good sometimes, but I envision millions of inter-addin calls happening each time the program is run, because the interfaces tend to provide fine-grained functionality. For example, a character stream interface has an indexer that gets called for each character. It wouldn’t be good for the CPU to spend most of its time marshalling.

    I would love to see an example that doesn’t use isolation, which shows how to optimize calls between addins for speed.

  15. System.AddIn in Framework V3.5 is about building hosts that load plug-in Add-Ins with functionality around…

  16. Tooraj says:

    Is it possible to have multiple hosts sharing the same addin? If yes, how the activation scheme works for the second host?

  17. Something worries me about the directory structure that seems to be expected by the AddInStore. It seems that when you call Update or Rebuild, it modifies the and files when necessary.

    Surely these things are going to be somewhere in Program Files? Or at least, the adapters, views, and contracts are all going to be installed wherever your program is installed.

    Some of the add-ins may be too I guess – installation of add-ins might be something you want to do centrally. But what if the user is non-admin? (As is the default with UAC on Vista. And as is common in some types of companies on XP. And as probably should have been the default from day 1 on NT…)

    I’m concerned that none of the documentation seems to address this rather important point. All the instructions and demos work just fine when you’re running the application out of whatever folder you happen to have built it in on your dev box. But how are we supposed to make this stuff deployable so that it will run in non-elevated scenarios?

    The prescribed directory structure, which mixes add-ins (which, presumably, we expect to add and maybe remove over time) into the same location as adapters views and contracts (which presumably don’t change over the lifetime of any single version of an app) seems to be essentially incompatible with UAC.

    I’m hoping that UpdateAddIns will be the answer – that this will let me set up per-user addin directories, and that these will maintain a seperate .store file from the master one.

    But it would be great to see a blog entry that discusses installation, deployment, and UAC. It’s one thing to build an application that works in a dev environment, but it seems like installation, deployment, and UAC are going to have a bunch of issues unique to an add-in solution.