Hosting Silverlight outside the browser
Update Oct 12, 2009: the source associated with this blog post is now available at http://firstfloorsoftware.com/blog/hosting-silverlight-outside-the-browser-sourcecode/.
I am constantly busy enhancing the Silverlight debugging experience in Silverlight Spy. During one of my (many) prototyping sessions I stumbled upon the Silverlight COM reference that is hidden somewhere in the Silverlight documentation.
The Silverlight COM Reference describes a set of COM interfaces that enables a Silverlight plug-in to be hosted outside the browser. A custom Silverlight host may be very useful to Silverlight Spy, so I decided to build a prototype. The Silverlight COM Reference doesn't provide a lot of information and there is little on this topic on the internet, but just enough to get things going. My goal was to build a custom host in C# and see how far I would get. A gazillion COM interface implementations and far too many AccessViolationExceptions later, I have had a break-through lately and my custom Silverlight host prototype entirely build in C# is actually working!
What is required
According to the COM reference, the host application is required to implement the IXcpControlHost and IXcpControlHost2 interfaces. These interfaces specify how the hosted Silverlight plugin should behave. The interface definitions are defined in an idl file, and I wrote the C# equivalents.
On creation of the Silverlight plugin, I needed to cast the IUnknown interface of the plugin to IOleObject and invoke IOleObject::SetClientSite and supply it an implementation of IServiceProvider. When the Silverlight control is activated, it will query for the IXcpControlHost interface using IServiceProvider::QueryService.
The Silverligh plugin itself implements the IXcpControl and IXcpControl2 interfaces. Both interfaces provide access to the settings and content properties of the plugin. Casting the control to IXcpControl and providing a source causes the plugin to invoke the IXcpControlHost::DownloadUrl. DownloadUrl expects a parameter of type IStream. The IStream interface is already defined in the System.Runtime.InteropServices.ComTypes namespace, so there is no need to write the interface yourself. Once a quick and dirty implementation of the IStream interface was in place, the silverlight plugin actually loaded and started showing of in my host.

What's next
I have my proof of concept now, it's possible to host a Silverlight plugin in a C# host outside the browser. There are however a number of issues I don't know yet how to solve. The HTML bridge, for instance, won't work as-is. There is no browser, so all HTML bridge calls will fail as the screenshot above demonstrates.
The implementation is far from finished (still crashing every now and then), but this opens a world of new possibilities. Too name a few; a light-weight Silverlight Spy, a Silverlight application test container, a Silverlight application that can be hosted in any .NET application without having to host a browser control, etc.
Published: March 2, 2009
This is very cool, and opens up a lot of possibilities for small and lightweight apps. I am guessing here, but I think the memory footprint of custom-hosted SL should be much smaller that of an equivalent WPF app. Can you allude to that, if possible.
Cheers
The one compelling area were I would definetly want to use SL outside of the browser is on a mobile platform... do you think I would be possible to host a SL app on the .net compact framework?
Rudi
This is very cool idea. However I don't understand why anyone will want to do that ?
Based on your Solution it can be done only on Windows (no Mac). If all you want is windows then why not use whole WPF stack ? Why care about silverlight at all ?
Awesome work Koen - Thank you very much for sharing this.
Hi Koen - it would be really nice if you published the source regardless of how well it works.
Great article! how do you attach the created silverlight plugin to a windows forms control? I tried to invoke the IOleObject::DoVerb method, but it doesn't work. It also does not call any methods of the IOleClientSite interface after calling SetClientSite... =(
Rishi: whether SL apps are more lightweight in terms of memory consumption in comparison to WPF remains to be seen
Rudi: SL on mobile will be supported by Microsoft some day, we won't need a custom host for that
Parag: true; a custom SL host only works on Windows, but as I mentioned there are various compelling scenarios to think of
David: sorry, no source code for now. Depending on SL3 features, I may want to use this for commercial purposes
Christopher: don't use AxHost. Create an instance using Activator.CreateInstance and cast it to IOleObject
Hi, cool post.
I've been trying to reproduce the steps you described but I'm failing to create the IXcpControlHost and IXcpControlHost2 interfaces and their implementation.
Any chance on sharing the code or parts of it?
Should wait for Silverlight 3 and have this functionality for free :)