Programming with .NET - Generalhttp://forums.silverlight.net//17.aspx/1?Programming+with+NET+GeneralGeneral discussions around authoring Silverlight .NET applications.Mon, 01 Jan 0001 00:00:00 -05001720251http://forums.silverlight.net//p/6576/20251.aspx/1?Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codePlugins, Reflection, the Downloader object and SecurityCritical code <p>Hi All</p> <p>There have been a number of posts lately about downloading assemblies in the background. So tonight I decided to try and work up a sample. I hit a few roadblocks, though. The main one is the failure of Assembly.Load to actually load the assembly.</p> <p>So, I was able to download the assemblies just fine using the downloader, and I have the code in place to do everything I need to do with them to get them on the canvas. However, calling Assembly.Load on the assembly (whether I just force it local or actually download it), resulted in a System.MethodAccessException on Assembly.Load(<em>assemblyname</em>).</p> <p>&quot;Attempt to access the method failed: System.Reflection.Assembly.LoadFrom(System.String)&quot;</p> <p>That seemed like a really an odd exception to get back given its usual interpretation,&nbsp;so&nbsp;I googled and managed to find <a class="" href="http://silverlight.net/forums/p/5158/15728.aspx" target="_blank"> this thread</a> which I completely missed the first time around:</p> <p>From reading the referenced articles (like <a class="" href="http://blogs.msdn.com/shawnfa/archive/2007/05/10/silverlight-security-ii-what-makes-a-method-critical.aspx" target="_blank"> this one</a>), I have to conclude that Assembly.Load(string) is considered critical and therefore, despite being exposed, is not something we can call from our application code. Sure enough, after loading it up in Reflector, I see it is indeed marked as such:</p> <pre>[<font color="#006018">SecurityCritical</font>] <font color="#1000a0">public</font> <font color="#1000a0">static</font> <font color="#006018">Assembly</font> <b><font color="#000000">Load</font></b>(<font color="#006018">AssemblyName</font> assemblyRef) { <font color="#006018">StackCrawlMark</font> <b>lookForMyCaller</b> = <font color="#006018">StackCrawlMark</font>.<font color="#006018">LookForMyCaller</font>; <font color="#1000a0">return</font> <font color="#006018">InternalLoad</font>(<font color="#006018">assemblyRef</font>, <font color="#800000">null</font>, <font color="#1000a0">ref</font> <font color="#006018">lookForMyCaller</font>, <font color="#800000">false</font>); } </pre> <p>Unless that changes and Assembly.Load is made SafeCritical, or a SafeCritical alternative is provided, it destroys the idea of background downloading assemblies and having a real componentized or plugin-style application model.</p> <p>Pete</p> 2007-11-09T04:12:03-05:0020252http://forums.silverlight.net//p/6576/20252.aspx/1?Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Plugins, Reflection, the Downloader object and SecurityCritical code <p>As far as I can see, the only (non-adequate) alternative is to write an HTTP handler which will emit XAML, which will reference needed assemblies. I.e. to perform selection of assemblies to load on server and not on client.</p> 2007-11-09T04:26:07-05:0020254http://forums.silverlight.net//p/6576/20254.aspx/1?Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Plugins, Reflection, the Downloader object and SecurityCritical code <p>If I understand what you're suggesting, that won't work, as other than the main assembly specified in x:Class, the other assemblies are all downloaded due to their inclusion in the manifest of the main assembly.</p> <p>Interesting idea, though :)</p> <p>Pete</p> 2007-11-09T04:34:55-05:0020260http://forums.silverlight.net//p/6576/20260.aspx/1?Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Plugins, Reflection, the Downloader object and SecurityCritical code <p>&nbsp;Pete,</p> <p>Thanks for trying this.&nbsp; I was one of the guys thinking about this incremental load idea.&nbsp; This must be something slated for the final release...there's no way you could build a RIA of any substance and not do incremental loading </p> <p>Thanks again!<br> &nbsp;</p> 2007-11-09T06:25:48-05:0020261http://forums.silverlight.net//p/6576/20261.aspx/1?Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Plugins, Reflection, the Downloader object and SecurityCritical code <p>Not at all. Do not use x:Class, use xmlns with clr-namespace like this:</p> <p><font color="#0000ff">&lt;Canvas x:Name=&quot;parentCanvas&quot;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns=&quot;<a href="http://schemas.microsoft.com/client/2007">http://schemas.microsoft.com/client/2007</a>&quot; <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:x=&quot;<a href="http://schemas.microsoft.com/winfx/2006/xaml">http://schemas.microsoft.com/winfx/2006/xaml</a>&quot; <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Loaded=&quot;Page_Loaded&quot; <br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x:Class=&quot;SilverlightProject1.Page;assembly=ClientBin/SilverlightProject1.dll&quot;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:plugin1=&quot;clr-namespace:Plugin1;assembly=ClientBin/Plugin1.dll&quot;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Width=&quot;640&quot;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Height=&quot;480&quot;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Background=&quot;White&quot;<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &gt;<br> &nbsp; &lt;TextBlock x:Name=&quot;tbLog&quot; Canvas.Left=&quot;0&quot; Canvas.Top=&quot;0&quot; Width=&quot;640&quot; Height=&quot;480&quot; /&gt;<br> &nbsp; &lt;plugin1:Page /&gt;<br> &lt;/Canvas&gt;</font></p> <p><font color="#0000ff"><font size="2">Then iterate Children of the canvas and you will get your loaded plugins. I tried this and just copied the Plugin1.dll from totally different (but of course SL)project with no references. So you need just text xmlns:plugin1=&quot;clr-namespace:Plugin1;assembly=ClientBin/Plugin1.dll&quot; in your XAML and corresponding file in your ClientBin. I have working sample which works, if you need it.</font></font><font color="#0000ff"><font size="2"></p> </font></font> 2007-11-09T06:31:02-05:0020283http://forums.silverlight.net//p/6576/20283.aspx/1?Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p>Just to correct you all, you can load assemblies downloaded with the Downloader class and then load them. I'm doing it now. I've made a plugins library if anyone wishes to check it out?&nbsp;</p> 2007-11-09T09:34:43-05:0020285http://forums.silverlight.net//p/6576/20285.aspx/1?Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p>It would be interesting if you show key lines of code which loads a downloaded assembly.</p> 2007-11-09T09:38:01-05:0020286http://forums.silverlight.net//p/6576/20286.aspx/1?Re+Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p>http://svn.digitalnetworks.co.uk/trunk/utilis/Utilis.Plugins/PluginDownloader.cs</p> <p>&nbsp;</p> <p>It's open source.&nbsp;</p> 2007-11-09T09:40:39-05:0020288http://forums.silverlight.net//p/6576/20288.aspx/1?Re+Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p>Thats strange. This directly contradicts what <a class="namelink" href="http://silverlight.net/members/Psychlist1972.aspx"> <strong><font color="#53b1e3" size="1">Psychlist1972</font></strong></a>&nbsp;says about Assembly.Load excpetion.</p> 2007-11-09T09:46:43-05:0020290http://forums.silverlight.net//p/6576/20290.aspx/1?Re+Re+Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p>&nbsp;It definitely does work (although I did just have a quick panic when I realised I was actually referencing the plugins from the main project since I was too lazy to copy them to the ClientBin folder everytime, but I just unreferenced them and did a test copying them manually)<br> </p> <p>&nbsp;The plugins <u><b>have</b></u> to be in the ClientBin in order to allow them to be loaded is the one stipulation I have discovered.<br> &nbsp;</p> 2007-11-09T09:57:17-05:0020295http://forums.silverlight.net//p/6576/20295.aspx/1?Re+Re+Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p>If that is working, that's pretty cool stuff, thanks for posting. The code looks almost the same as what I have. So, I would like to check a few things to make sure it doesn't just appear to be working:</p> <p>1. Are you sure the files aren't coming down with the initial application load (having to be in ClientBin seems to point to that being the case). You can use Fiddler to check this out. Make sure you clear your browser cache first.</p> <p>2. Since you had to reference them (I know you unreferenced and tried again, but sometimes caching can get in the way here), can you check to see if they show up in the metadata of your main assembly?</p> <p>3. Can you put an exception handler around your Assembly.Load call and spit out something if you get an exception? In my code, since the Assembly.Load happened as a result of the download complete event, the exception was swallowed and never displayed.</p> <p>I was trying to do something where the main assembly knew nothing about the downloaded assemblies other than that a class in there implemented a specific interface. I had a button on my main page - when you click it, the download happens. That way I could really tell exactly when the files were downloaded and the classes instantiated.</p> <p>Pete</p> 2007-11-09T12:24:16-05:0020305http://forums.silverlight.net//p/6576/20305.aspx/1?Re+Re+Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p>1. Cleared browser cache, and installed fiddler to check it out, added a 5 second Thread.Sleep() before it started looking for plugins, and there was a 5 second delay (at a guess, i wasn't actually timing) before fiddler showed the http requests for the plugin assemblies.</p> <p>2. Nope not there.<br> </p> <p>3. No exception what so ever, loads fine. I did have to play around a bit before settling on this solution, initially tried downloading from anywhere and just loading a byte[] but Assembly.Load hates that, which landed me in the position that it'll only work if the assembly is downloaded using the Downloader class, and it must be in the ClientBin folder (i tried using a seperate /plugins/ folder but it also failed, i think anyway from memory).<br> </p> <p>&nbsp;</p> <p>Main assembly knows nothing of the files, queries the server for plugin assembly name and location then creates a Plugin object from my Utilis library like so:<br> new Plugin(string name, Uri location);<br> e.g.<br> new Plugin(&quot;Facilis.Editor.Plugins.Html, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null&quot;, new Uri(&quot;ClientBin/Facilis.Editor.Plugins.Html.dll&quot;, UriKind.Relative));</p> <p>Then just feed all the Plugin objects to the PluginDownloader and it goes off and gets them. I'll probably write some documentation on the Trac for it in a bit.<br> </p> <p>There is the common library that both the plugins and main assembly reference with the plugin interface and that gets pulled down at initial load, but the others don't.<br> &nbsp;</p> <p><br> &nbsp;</p> 2007-11-09T13:54:59-05:0020307http://forums.silverlight.net//p/6576/20307.aspx/1?Re+Re+Re+Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Re: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p>I've written some basic documentation <a href="http://trac.digitalnetworks.co.uk/utilis/wiki/Utilis.Plugins" target="_blank"> here</a> if you fancy looking.<br> </p> 2007-11-09T14:10:01-05:0020340http://forums.silverlight.net//p/6576/20340.aspx/1?Re+Re+Re+Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Re: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p>Thanks. I'm going to check that out and see what's different with my configuration. Your stuff working seems to contradict what the security documentation says. I also dont't get why my rather simple example failed on assembly.load. I'll dig deeper and see if I can understand what is going on there.</p> <p>My pattern, with the exception of using attributes, is very similar to yours. I have an IPlugin and use reflection to find out what classes in the assembly implement IPlugin. Right now, the assembly names are hard-coded in the manager class to avoid additional external dependencies.</p> <p>Re: ClientBin: I had the opposite result. I found that I had to keep everything in the same folder as the Page.xaml in order for the downloader to download it. I moved all the assemblies to that folder, and then the download worked. This is consistent with the preloader example in the getting started, but does seem&nbsp;a bit silly.</p> <p>Thanks for posting your experience on this. The plot thickens! :)&nbsp;</p> <p>Pete</p> 2007-11-09T18:48:57-05:0020346http://forums.silverlight.net//p/6576/20346.aspx/1?Re+Re+Re+Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Re: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p>Ok, that was really dumb on my part and I'm really glad that there are other folks out there trying stuff like this :)</p> <p>I was calling Assembly.LoadFrom instead of Assembly.Load. I think that was just a control-space error, not a conscious decision. Once I changed to assembly.load, it worked. That still doesn't fit in to the security discussion from that other link, but working is working.</p> <p>Thanks a&nbsp;TON for pointing out that there really is a working solution to this!&nbsp;I would not have revisited this until the next release if you hadn't pointed that out.</p> <p>I now have a working, but unpolished, sample that shows how to load a usercontrol dynamically to support segmented/preloader-type applications written 100% in managed code rather than the combination managed/unmanaged sample that is in the quickstarts. Once I polish up a couple bits, I'll post it (probably in a couple days)</p> <p>FWIW, all the assemblies in my sample are in the same folder as the page.xaml, which isn't ClientBin. I think generally all your DLLs need to be in the same folder, and that can be either the project main folder, or something hanging off of it.</p> <p>Pete</p> 2007-11-09T19:35:10-05:0020368http://forums.silverlight.net//p/6576/20368.aspx/1?Re+Re+Re+Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Re: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p></p> <blockquote><span class="icon-blockquote"></span> <h4>Psychlist1972</h4> <br> I now have a working, but unpolished, sample that shows how to load a usercontrol dynamically to support segmented/preloader-type applications written 100% in managed code rather than the combination managed/unmanaged sample that is in the quickstarts. Once I polish up a couple bits, I'll post it (probably in a couple days) <p></p> <p>FWIW, all the assemblies in my sample are in the same folder as the page.xaml, which isn't ClientBin. I think generally all your DLLs need to be in the same folder, and that can be either the project main folder, or something hanging off of it.<br> </p> </blockquote> <p></p> <p>That's interesting to know, I shall have to try a few experiments on that then.</p> <p>As for posting in the next few days, I was wondering if you fancied helping out with the library I have already started making, which is opensource. It's licensed under the MIT license which means both opensource and closed source projects can use it, it's about the most liberal license there is.</p> <p>Admittedly I've already asked if anyones interested and no one said anything so if you aren't that's fair enough, I just figured if we created useful things like this now then when silverlight 1.1 hits final there will already be these libraries that people can use to speed up there development and increase adoption. And due to the nature of opensource anyone can take a look at it and see if there are any improvements that can be made and put them forward. My aim is to (ideally) make something similar to mootools for javascript, which in my opinion helps things along a lot.</p> <p>Damien&nbsp;</p> 2007-11-09T23:30:52-05:0020371http://forums.silverlight.net//p/6576/20371.aspx/1?Re+Re+Re+Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Re: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p></p> <blockquote><span class="icon-blockquote"></span> <h4>damoxc</h4> <p>As for posting in the next few days, I was wondering if you fancied helping out with the library I have already started making, which is opensource. It's licensed under the MIT license which means both opensource and closed source projects can use it, it's about the most liberal license there is.</p> <p>Damien&nbsp;</p> <p></p> </blockquote> <p></p> <p>Hi Damien</p> <p>Not right now. With a major set of changes coming, I hesitate to invest in anything more than samples when it comes to reusable Silverlight 1.1 code. I may revisit after the control model is fleshed out more, if you're still interested at the time.</p> <p>That being said, I checked out what you have and it is extremely cool. I feel it will be a huge benefit to the Silverlight community both in its current state and when it is complete. If anyone here hasn't checked it out, please take a gander.</p> <p>Pete</p> 2007-11-10T00:25:48-05:0020372http://forums.silverlight.net//p/6576/20372.aspx/1?Re+Re+Re+Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Re: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p>I fully intend to run this through to silverlight final (due to the application I'm making going to be used in production eventually, and that application references the library) so once that happens and you're still interested that would be ace [:)]</p> <p>&nbsp;And if anyone else feels like helping me make the transitions through the silverlight changes it would only help things.<br> &nbsp;</p> <p>&nbsp;</p> 2007-11-10T00:34:10-05:0020381http://forums.silverlight.net//p/6576/20381.aspx/1?Re+Re+Re+Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Re: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p>Hi all</p> <p>I posted a quick and dirty sample that illustrates that <a class="" href="http://community.irritatedvowel.com/blogs/pete_browns_blog/archive/2007/11/09/Silverlight-Assembly-Preloader-in-Managed-Code.aspx" target="_blank"> here</a>.</p> <p>It doesn't even come close to the plugin framework damoxc is doing (which is quite nice), but it serves its purpose :) My main goal here was to find a managed way to get a preloader working for other application components. The sample in the quickstarts works ok, but it just smacks me as funky. Plus, due to the way the page was swapped out at runtime, the animation never worked correctly when I used that sample when doing the preloader for the carbon calculator.</p> <p>Pete</p> 2007-11-10T03:58:33-05:0020644http://forums.silverlight.net//p/6576/20644.aspx/1?Re+Re+Re+Re+Re+Re+Plugins+Reflection+the+Downloader+object+and+SecurityCritical+codeRe: Re: Re: Re: Re: Re: Plugins, Reflection, the Downloader object and SecurityCritical code <p>Pretty cool stuff guys, I can see where this can become extremely handy. Imagine allowing 3rd parties to create new UIs for your applications, and just allow the users to pick which &quot;skin&quot; (which actually is an assembly) they want to use.</p> <p>Your generic FindByName is nice, I might have to steal that&nbsp;one. Wierd that&nbsp;they did&nbsp;not implement it by default. Oh well,&nbsp;it's still alpha&nbsp;I guess :)&nbsp;</p> <p>&nbsp;Only small issue I saw in the code was missing using statements around streams.</p> <p>Roger Larsen</p> 2007-11-13T18:40:28-05:00