<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>CLR Add-In Team Blog : Behind the Scenes</title><link>http://blogs.msdn.com/clraddins/archive/tags/Behind+the+Scenes/default.aspx</link><description>Tags: Behind the Scenes</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Add-In Lifetime Management [Pete Sheill, Jim Miller]</title><link>http://blogs.msdn.com/clraddins/archive/2007/07/18/add-in-lifetime-management-pete-sheill-jim-miller.aspx</link><pubDate>Wed, 18 Jul 2007 02:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3925512</guid><dc:creator>CLR Add-In Team</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/clraddins/comments/3925512.aspx</comments><wfw:commentRss>http://blogs.msdn.com/clraddins/commentrss.aspx?PostID=3925512</wfw:commentRss><wfw:comment>http://blogs.msdn.com/clraddins/rsscomments.aspx?PostID=3925512</wfw:comment><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;A good question to ask when evaluating a design is ‘how is the lifetime of this object or component managed?’&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That is, &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-add-space: auto; mso-list: l2 level1 lfo2"&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face="Times New Roman" size=3&gt;How do you know it isn’t needed anymore? &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-add-space: auto; mso-list: l2 level1 lfo2"&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face="Times New Roman" size=3&gt;Is it possible to release the resources while the object is still in use?&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-add-space: auto; mso-list: l2 level1 lfo2"&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face="Times New Roman" size=3&gt;Is it possible to “leak” the resources by not releasing them at all?&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-add-space: auto; mso-list: l2 level1 lfo2"&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face="Times New Roman" size=3&gt;How soon after the object isn’t needed are the resources released?&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 0pt 1in; mso-add-space: auto"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;How does this apply to the managed add-in model?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you are content to keep the add-in loaded until the process exits (and the system cleans up the entire process) you can stop reading right away, as this topic isn’t of particular interest to you. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;One of the greatest benefits of managed code, of course, is automatic lifetime management (garbage collection).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Within an application domain (“appdomain”) objects no longer referenced by “live” objects are automatically reclaimed by the garbage collector and there’s a standard mechanism (finalization and IDisposable) to release any unmanaged resources those objects are using.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;The resources to be reclaimed include the memory for the instance members, any operating system handles, database connections, etc.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Another resource, often overlooked in managed code, is the memory taken by the code itself, including the JIT-compiled code.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Releasing this last resource is not possible if the code is loaded in the same appdomain as the host.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We simply don’t have a way to unload an assembly without unloading the appdomain that hosts it.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;In general, there are three ways to manage the lifetime of objects:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo3"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;1.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Garbage collection&lt;/B&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This works within a single appdomain as described above.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unfortunately, there’s no good general purpose solution for use in distributed systems (although it’s been an active research area for years).&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo3"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;2.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Reference counting.&lt;/B&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is probably familiar to you from COM and other systems.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When you create an object you set a variable to 1, whenever you add a new reference to it you increment the variable (“addref”), when you release a reference you decrement the variable (“release”).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When the variable goes to 0 there are no more references and you can release the object and any data it holds.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This works as long as there are no cycles between objects, but leads to memory leaks when a cycle occurs.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo3"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;3.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;Sponsorship.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/B&gt;This is the mechanism used for both DCOM and .NET Remoting.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The idea is that when you create a remote object you declare something as a “sponsor” for the object and periodically ask the sponsor if the object is still needed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the sponsor says it isn’t needed, or if you can’t reach the sponsor after some number of tries, you can release the object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;One common way of implementing sponsorship is what’s called the “lease” model where the sponsor provides a lease that states how long the object should be considered alive and the sponsor isn’t contacted until the lease expires.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt; mso-add-space: auto"&gt;&lt;FONT face="Times New Roman" size=3&gt;The managed add-in framework uses a combination of all three of these mechanisms.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Within a single appdomain it uses garbage collection.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But it gets a lot more interesting when the add-in is being run in a separate appdomain in the same host process, or in a separate process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even though the HostSideAdapter has a reference to the AddInSideAdapter, because the AddInSideAdapter is “remote” it is subject to reclaiming under normal garbage collection.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt; mso-add-space: auto"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt; mso-add-space: auto"&gt;&lt;FONT face="Times New Roman" size=3&gt;In designing the lifetime management system for managed add-ins, our goal was to make simple cases simple but still allow more complicated systems to be built.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The framework itself takes responsibility for the sponsorship model, but exposes a reference counting model to control the behavior of the sponsor.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In simple cases the reference count is maintained automatically by the framework, too, using the garbage collector and finalization.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The rest of this article talks about the details of this implementation.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 0pt; mso-add-space: auto"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;In the case where the add-in is isolated from the host, either in a different appdomain or a different process, the garbage collector still reclaims objects when they are no longer referenced.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you release the reference to the HostSideAdapter the garbage collector will release its memory.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But what about the corresponding AddInSideAdapter and the add-in itself?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And what about the case where you allowed the add-in framework to create an appdomain for running the add-in – when is the appdomain released?&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt; mso-add-space: auto"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 0pt; mso-add-space: auto"&gt;&lt;FONT face="Times New Roman" size=3&gt;The standard solution to the issue of keeping the AddInSideAdapter alive in .Net Remoting is to use leases and sponsorship to keep the remote object alive.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;While we do use sponsorship underneath, we decided not to expose this to the add-in or pipeline developers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Instead, we use a variant of the “ref counting” technique to keep remote objects alive by providing the methods AcquireLifetimeToken() and RevokeLifetimeToken().&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When the HostSideAdapter is constructed, it immediately makes a call to AcquireLifetimeToken() on the AddInSideAdapter to tell the AddInSideAdapter that it has a reference to it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When the HostSideAdapter is disposed of or reclaimed, it will make a call to RevokeLifetimeToken() on the AddInSideAdapter to let it know that it is done referring to it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Usually, this will lead to the AddInSideAdapter and the add-in being reclaimed.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;Let’s consider a simple scenario first – an add-in in its own appdomain in the host process.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Say you have activated an add-in using the overload of Activate() that takes an AddInSecurityLevel.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This method creates a new appdomain to host the add-in.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As described in the post on activation, the HostSideAdapter calls AcquireLifetimeToken() on the AddInSideAdapter when it is created.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This increments the “ref count” on the AddInSideAdapter to one.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As a convenience, this is usually done by constructing and holding a ContractHandle, passing in the AddInSideAdapter to the constructor -- the constructor of the ContractHandle actually calls AcquireLifetimeToken.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We’ll assume that this is the case for this example.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As long as this ref count is above zero, the AddInSideAdapter will stay alive in memory.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Since it has a reference to the add-in, the add-in will therefore also stay alive in memory.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;The host uses the add-in through the HostViewOfAddIn (previously called HostAddInView), and then decides that it no longer needs it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The variable that used to reference it is set to null.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At some later point, when the garbage collector runs, it notices that the HostViewOfAddIn is no longer needed, and therefore neither is the ContractHandle.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It calls the finalize method of the ContractHandle, which then calls RevokeLifetimeToken() on the AddInSideAdapter.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The AddInSideAdapter decrements the ref count to zero.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This triggers cleanup – the add-in is no longer needed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the AddInSideAdapter has been implemented by deriving from the framework class called ContractBase (highly recommended), then the following happens:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo1"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;1)&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;A flag is set to end the sponsorship (in remoting) that is keeping the object alive.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo1"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;2)&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;OnFinalRevoke() is called, allowing the derived class to clean up any native resources it holds.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We chose to name the method this way instead of calling it Dispose() because Dispose() is a public method typically called by an external object, while this method is a protected method called by the object itself.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo1"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;3)&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;We unload the appdomain with a call to AppDomain.Unload().&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Before unloading completes, the finalizers of all the objects in the appdomain will run.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;So in this example, the cleanup happened without any explicit instruction to do so by the host or the add-in, similar to normal single-appdomain garbage collection.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;The nice part about this approach is that the host code is isolated from the lifetime management of the add-in.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It just uses the HostViewOfAddIn as it would any other managed object, without doing any reference counting itself – because that code is only done in the adapter.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When there are no more live references to the HostViewOfAddIn, all the memory and resources of the adapters and add-in will automatically be reclaimed.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;There are times where steps #1 and #2 will happen, but not #3.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That is, the add-in is ready for cleanup, but the appdomain is not.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the appdomain was not created during activation of this add-in, then the AppDoamin will not be unloaded here.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The appdomain may be the default host appdomain, it may have been explicitly created by the host, or it may have been created for another add-in.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In any case, there are other objects in the appdomain that are likely still in use, so we can’t unload it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Stated another way, if we didn’t create the appdomain, then we won’t unload it. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;Assuming that the appdomain was created specifically for the add-in, there is another situation that will postpone the cleanup.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Reference counting relies on an object "owning" its own memory and other resources.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That is, the object itself is responsible for deallocating the resources at the right time, once it is sure that no other object needs it. The appdomain created for the add-in will typically have the same lifetime as the add-in.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;While we could have kept a separate ref count for the appdomain, having the appdomain own itself, we decided to simplify things and have the primary add-in own the appdomain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Therefore the two always have the exact same lifetime.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Only when the ref count of the add-in goes to zero does the appdomain get unloaded, causing any objects in that appdomain to be finalized and unavailable.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;One question that might arise is what happens if the add-in creates an object and passes a reference to it to the host, and then goes out of scope before the host uses the object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A separate pipeline is created for the object as it is passed to the host, similar to the pipeline between the host and the add-in.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If the add-in's reference count went to zero, the add-in and the appdomain would be reclaimed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But then if the host still held a reference to the object and tried to call one of its methods, it would fail with an AppDomainUnloadedException.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;To address this, we don't allow the add-in's reference count to go to zero in this situation until the host no longer references the object.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When the object is passed to the host and a pipeline is created for it, we look up the owner of the appdomain and increment its ref count.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then when the object is no longer needed and the pipeline is being finalized we decrement its ref count.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Only at this point can the ref count of the primary add-in go to zero, leading to the cleanup of the appdomain. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;If the host calls Activate to create a new appdomain for a new add-in, then uses that same appdomain in subsequent calls to activate secondary add-ins, a similar process happens.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The secondary add-ins increment the ref count of the primary add-in, so that the appdomain won't be cleaned up while they are still in use.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The secondary add-ins decrement the primary add-in's ref count when they are no longer referenced, permitting appdomain cleanup to proceed.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;Note that this version of reference counting improves on some other versions in that you can’t accidentally remove a reference that a different object created.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s because AcquireLifetimeToken() returns a unique “token” number that should be stored and passed back to RevokeLifetimeToken().&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Revoking a token that you didn’t previously acquire will by and large have no effect, aside from causing an InvalidOperationException to be thrown.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman','serif'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;There’s more to say about lifetime management, but we’ll leave that for later posts.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It’s a multifaceted issue, but we hope that most hosts and addins will be able to be written as if all the resource cleanup is governed by garbage collection, even though there is a bit more to it than that underneath. &lt;/SPAN&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3925512" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/clraddins/archive/tags/Behind+the+Scenes/default.aspx">Behind the Scenes</category><category domain="http://blogs.msdn.com/clraddins/archive/tags/Architecture/default.aspx">Architecture</category></item><item><title>Behind the Scenes: Activation [Pete Sheill]</title><link>http://blogs.msdn.com/clraddins/archive/2007/06/28/behind-the-scenes-activation-pete-sheill.aspx</link><pubDate>Thu, 28 Jun 2007 18:42:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3586089</guid><dc:creator>CLR Add-In Team</dc:creator><slash:comments>18</slash:comments><comments>http://blogs.msdn.com/clraddins/comments/3586089.aspx</comments><wfw:commentRss>http://blogs.msdn.com/clraddins/commentrss.aspx?PostID=3586089</wfw:commentRss><wfw:comment>http://blogs.msdn.com/clraddins/rsscomments.aspx?PostID=3586089</wfw:comment><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;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.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I’ll be referring to the discovery and activation as discussed &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/msdnmag/issues/07/02/CLRInsideOut/default.aspx" mce_href="http://msdn.microsoft.com/msdnmag/issues/07/02/CLRInsideOut/default.aspx"&gt;&lt;FONT face="Times New Roman" color=#0000ff size=3&gt;here&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face="Times New Roman" size=3&gt; and the segments of the add-in pipeline as discussed &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/msdnmag/issues/07/03/CLRInsideOut/default.aspx#S1" mce_href="http://msdn.microsoft.com/msdnmag/issues/07/03/CLRInsideOut/default.aspx#S1"&gt;&lt;FONT face="Times New Roman" color=#0000ff size=3&gt;here&lt;/FONT&gt;&lt;/A&gt;&lt;A href="http://msdn.microsoft.com/msdnmag/issues/07/03/CLRInsideOut/default.aspx#S1" mce_href="http://msdn.microsoft.com/msdnmag/issues/07/03/CLRInsideOut/default.aspx#S1"&gt;&lt;/A&gt;&lt;FONT face="Times New Roman" size=3&gt;.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let’s say you have discovered a single token for an add-in, and you have decided to activate it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;To isolate the add-in from the host you chose to run it in its own new appdomain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;What happens next when you call one of the Activate() methods on the add-in token?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let’s enumerate all of the steps that the system takes:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;1.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;The appdomain is created with the permissions that you specified in the call to Activate().&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;2.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;The add-in assembly is loaded into that appdomain through a call to Assembly.LoadFrom(), passing in the location of the assembly.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The add-in type will not be loaded in the host’s appdomain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In other uses this call can cause loader context issues if not used carefully, but we’ve taken steps to avoid them here.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact, this method was created specifically to support add-in scenarios.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;3.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;We use reflection to call the no-argument constructor for the add-in to create an instance in that appdomain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;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.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;At this point we have an instance of the add-in running in its own appdomain.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now we need to connect it to the host.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;4.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;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.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;(This adapter implements a Contract interface and derives from MarshalByRefObject through the intermediate ContractBase class.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;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.)&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;5.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;The activation code passes the add-in adapter back to the host’s appdomain typed as the Contract that it implements.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;6.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;An instance of the HostSideAdapter is constructed in the host’s appdomain, with the AddInSideAdapter being passed in as its only argument.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The exact HostSideAdapter type is determined by examining the add-in token.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This adapter derives from (or implements) the HostViewOfAddin that the host compiled against.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;7.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;The activation code returns the host-side adapter to the host, typed as the HostViewOfAddin.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;The host will sometimes do further initialization of the add-in through a separate call, passing in any needed arguments.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Then it is up to the host and add-in to communicate as needed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Activation has completed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;Do the adapters need to be public?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Actually, no.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;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.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That’s because we use reflection to invoke the constructor, and given enough permission, reflection can invoke non-public constructors.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;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.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;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.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;It needs to call the AcquireLifetimeToken() member, specified in the IContract interface, of that adapter.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;That is part of another big topic, lifetime management.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We’ll discuss that in another post.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="Times New Roman" size=3&gt;This is one way to activate an addin in this model.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;There are also some other different ways you could activate the same addin.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You could choose to activate it in the same appdomain as the host.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You could also choose to activate it in an entirely separate process, if isolation matters above all else.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We’ll explore those options more in later posts.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3586089" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/clraddins/archive/tags/General/default.aspx">General</category><category domain="http://blogs.msdn.com/clraddins/archive/tags/Behind+the+Scenes/default.aspx">Behind the Scenes</category></item><item><title>Behind the Scenes of Add-In Discovery in the Orcas System.AddIn [Jesse Kaplan]</title><link>http://blogs.msdn.com/clraddins/archive/2007/02/08/behind-the-scenes-of-add-in-discovery-in-the-orcas-system-addin.aspx</link><pubDate>Fri, 09 Feb 2007 00:19:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1629857</guid><dc:creator>CLR Add-In Team</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/clraddins/comments/1629857.aspx</comments><wfw:commentRss>http://blogs.msdn.com/clraddins/commentrss.aspx?PostID=1629857</wfw:commentRss><wfw:comment>http://blogs.msdn.com/clraddins/rsscomments.aspx?PostID=1629857</wfw:comment><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Details about the System.AddIn’s Implementation of Add-In Discovery&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;A href="http://blogs.msdn.com/clraddins/archive/2007/01/26/different-approaches-to-add-in-discovery.aspx" mce_href="http://blogs.msdn.com/clraddins/archive/2007/01/26/different-approaches-to-add-in-discovery.aspx"&gt;&lt;FONT face=Calibri size=3&gt;Last time&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Calibri size=3&gt; we discussed several common approaches to add-in discovery and some of the pros and cons of each.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;We reviewed type hierarchy, custom attribute, and xml manifest based discovery systems and primarily evaluated them on three high level criteria: development complexity, performance, and add-in developer experience. This time I’d like to go into the details on what we developed and how it builds on the lessons we learned while evaluating previous solutions. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Implementation Overview&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;We had two high level goals in mind when we developed our discovery system: minimize complexity for the add-in developer and make the solution fast enough to be used at runtime. We wanted the add-in developer experience to be as close to “inherit from an abstract base class and run with it” as possible and we wanted hosts to be able to use the UI thread to discover add-ins.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;Fundamentally the system we developed is mostly based on the custom attribute approach but with intelligent caching and updating that lets you avoid doing the work at runtime. &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;We tried to capture the add-in developer experience of the custom attribute solutions with the performance of the manifest based approach. &lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;At development time the add-in developers experience is as simple as with the custom attribute model: they inherit from the right abstract base class, apply the AddInAttribute, and then start writing the add-in. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;As we noted earlier however, the custom attribute based approaches have the downside that computing this information requires loading and examining a bunch of assemblies and are too slow to do on application start up or on the UI thread. With this in mind we went a step further and built a system that caches this information to disk. This also led us to split our discovery into two phases: Update and Find. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'"&gt;AddInStore&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'"&gt;.Update(addinPath);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'"&gt;IList&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;lt;&lt;SPAN style="COLOR: teal"&gt;AddInToken&lt;/SPAN&gt;&amp;gt; tokens = &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'"&gt;AddInStore&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'"&gt;.FindAddIns(&lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: teal"&gt;AddInType&lt;/SPAN&gt;), addinPath);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Update Details&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;The update phase is where we do the work to examine the add-in directory and build the store (or cache) of all the add-ins available there. For each sub directory at the provided path we look at each dll in the directory looking for a type that has [AddInAttribute] applied to it and record the information in the attribute and the base class of the add-in and store all the found information in a file called AddIns.store in the directory provided. One thing to note here is that we examine all of these assemblies in a different AppDomain and we use ReflectionOnly loading: this ensures that the add-in code is never executed until it is activated and that a call to update does not pollute the hosts AppDomain with these assemblies. Rather than recomputing all this information at each call to update we examine the timestamps of the various items in this directory and compare it to the existing store file (if there is one) and decide whether or not there is anything new we need to look at and if not we return quickly. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;In addition to providing an update method that does this work we also ship the command tool AddInUtil.exe with the framework that was designed to be called with a custom action in an installer or via a build script. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;By providing both a runtime Update method and the command line tool we leave an important decision up to the host: the host can choose to call AddInStore.Update from within the host app and thus make the add-in deployment experience truly an x-copy one, or it can require that add-ins run the tool themselves as part of their setup. In addition we’ve also ensured that the store file itself is x-copyable along with the add-in directory and so if, for example, a host ships with a few add-ins pre-installed it can build the store file when it’s building its setup and just deploy that store file along with the add-ins. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;FindAddIns Details&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;In FindAddIns the host passes us the type it wants to use to talk to the add-ins, the directory it wants us to look in and it receives back a collection of AddInTokens representing all the add-ins we found that can be used through the provided abstract base class. This method was designed to be usable during application startup and on the UI thread and we go out of our way to make sure that no types are ever loaded during this call and that the only files we read are the store files at the specified location. If no one (either the host or the add-in) performed an update on that location then no add-ins will be found. Another interesting thing we do is that we keep the store file in memory so that subsequent calls to FindAddIns on the same directory will not require us loading the file again: we simply check to see if the file has been updated since we last loaded it from disk and only reload it if necessary. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;The AddInToken objects returned from a FindAddIns call are the objects that the host can actually activate to get back an instance of the add-in. They also contain metadata about the add-in that the host can use to decide which add-ins it wants to load: the add-in always provides a friendly name for itself and can optionally specify a version, publisher, and a short description.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All of this information was originally recorded by examining, but not loading, activating, or executing, the add-in during the Update call and was stored in the token object during FindAddIns: this means that the host can get specific information about the add-ins and make informed decisions about which ones to activate without having to every execute any add-in code. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Putting it Together&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;Let’s start with reviewing our three high level goals: &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1"&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri size=3&gt;Minimize complexity of the add-in developer&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1"&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri size=3&gt;Performance of discovery code at runtime&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 10pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1"&gt;&lt;SPAN style="FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;·&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Calibri size=3&gt;Ease of host development&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;Fundamentally all an add-in developer has to do with our system is to inherit from the right abstract base class, apply the [AddInAttribute] to the add-in, and then copy the add-in to the directory the host looks. This was our pri-1 requirement and we’ve made sure that it’s just about as low overhead on the add-in developer as possible. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;As far as performance is concerned we leave it up to the host to decide what is most important: can it handle the cost of updating the stores at runtime when new add-ins are installed and reduce the complexity of add-in deployment, or is it acceptable to require a custom action in the installer. If the add-in deployment is responsible for updating the store then our solution is faster than the xml based discovery – since we only need to look at one file and we don’t have to load an xml parser to do so – and if the host decides to do runtime Update then it only pays the cost of discovery when new things are installed and we handle caching that information to disk for future look ups. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Finally we come to the ease of host development and here we may have the best story of all: while our solution may be harder to develop than the solutions we reviewed last time, we’ve removed this complexity since will be shipping as part of the framework.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;We really do let you install and find add-ins in two lines of code: &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'"&gt;AddInStore&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'"&gt;.Update(addinPath);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'"&gt;IList&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;lt;&lt;SPAN style="COLOR: teal"&gt;AddInToken&lt;/SPAN&gt;&amp;gt; tokens = &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: teal; FONT-FAMILY: 'Courier New'; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'"&gt;AddInStore&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes; mso-fareast-font-family: 'Times New Roman'"&gt;.FindAddIns(&lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: teal"&gt;AddInType&lt;/SPAN&gt;), addinPath);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;At the beginning of the last article I mentioned some exotic discovery mechanisms such as in a database, embedded in a document, and over RSS. We’re actually working with partners who are building these mechanisms on top of our discovery system and down the line we’ll have a series of blog posts demonstrating some of these techniques. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=Calibri size=3&gt;In our next behind the scenes post we’ll pull back the curtains on the magical third line of code that activates your add-ins: &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;token.Activate&amp;lt;&lt;SPAN style="COLOR: teal"&gt;AddInType&lt;/SPAN&gt;&amp;gt;(&lt;SPAN style="COLOR: teal"&gt;AddInSecurityLevel&lt;/SPAN&gt;.Internet)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1629857" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/clraddins/archive/tags/General/default.aspx">General</category><category domain="http://blogs.msdn.com/clraddins/archive/tags/Behind+the+Scenes/default.aspx">Behind the Scenes</category></item></channel></rss>