Wednesday, December 30, 2009

Silverlight Hosting in WPF

Ok so we know this has been done. Yawn, and it can be done any number of ways from hacking it in a browser control but actually doing it in WPF without the browser control can be a huge pain. Here is a little trick that helps you do just that without all the jumping around.

Jeremiah, (this programmer extraordinaire with apparently WAY to much time on his hands) wrote this little codeplex project that is a 'WPF Panel' that hosts Silverlight. http://silverlightviewport.codeplex.com/

pretty slick, if you dive into the code it is kind of complicated but to use it is straight forward enough. If you download the project and run it you can see it in his test application running a xap in Window1.xaml.

<slvp:SilverlightViewportElement BaseUrl="http://silverlight.net/"
Source="http://silverlight.net/clientBin/showcasenav/ShowcaseNav.xap"
ViewportSize="550,550"
RenderFps="40"
x:Name="slViewport">
<slvp:SilverlightViewportElement.Effect>
<DropShadowEffect BlurRadius="50" />
</slvp:SilverlightViewportElement.Effect>
<slvp:SilverlightViewportElement.LayoutTransform>
<RotateTransform Angle="10" />
</slvp:SilverlightViewportElement.LayoutTransform>
</slvp:SilverlightViewportElement>

you'll notice this is all the standard WPF fare but lets look at the properties on the main panel itself. First is our base url that tells the control the domain in which the xap or silverlight application lives. Next we have the 'Source' which points to our xap file. We then set a view port size as 'ViewportSize' and then the last one we will mention is 'RenderFps' which is the 'speed' that the Silverlight is 'rendered' into your panel. In effect your app now runs in the WPF app. Nice and clean as long as you don't look at the source for the panel which is more a work of art... :)

Self Editing XML File

This particular post is a rehash of one I didn't some years back. Basically it is a little technique I developed some 7 or 8 years ago to solve a simple database issue once but I wanted only one file to exist in this case the exe or sorts that was also the xml file. As this applies to Silverlight in the since that I can use this application technique to also be used as a shell for a Silverlight application without all the silly security barriers... > : )

DISCLAMIER: I AM NOT RESPONSIBLE FOR THE USE OF THIS TECHNOLOGY IN FACT YOU SHOULD STOP READING NOW BEFORE YOU HURT YOUR SELF OR OTHERS...

But lets not focus on that... lets focus on the mechanics of what we are talking about. A long time ago in a galaxy far far away there was a company called Microsoft that as the center of the universe they released this cool little DHTML technology back before they changed the name to AJAX and it was still cool called an HTA or Hyper Text Application or 'HTml Application' which basically is an HTML file with the file extension of '.hta' instead of '.html' and when you have one of these locally and you click on it, it then renders without all that silly browser chrome/buttons etc. oh and with the rights of a win32 app installed locally...

Basically with a little markup you can control and manipulate the browser chrome and any com object on the system with a script friendly API you can talk to.

Now this 'hta' thing works if the page is hosted on a web page too... albeit you get ONE security dialog that doesn’t really explain what is going on and if the user clicks ok the hta runs as a locally installed app w/o silly security sandbox stuff going on... and yes that basically means it can for all intents and purposes fdisk your hard drive...

DISCLAMER 2: STOP READING HERE AND DON'T DO THIS STUFF.

Like anything though this can be used for good and evil.

Ok back to how to-do it. if you Google HTA on Bing (or Google) you can get the reference material for hta's but basically it is an html file that runs in a version of IE w/o the sandbox. so basically any html that works there works in the hta too with the added addition of this tag:

<HTA:APPLICATION id="oVDProcess"
applicationName="Virtual Desktop - Lite"
singleinstance="yes"
caption="no"
contextmenu="no"
innerborder="no"
scroll="no"
showintaskbar="no"
version="1.0.032"
SELECTION="no"
windowState="normal"
icon="img\im_gray.ico"
/ >

Now as mentioned you can also access any of your com objects the XML Document object or the 'File System' object... here is some sample code from my magic self editing file:

var oDOM = null;
var giHeight = 360;
var giWidth = 800;

function initFrm() {
try {
self.resizeTo( giWidth, giHeight );
self.moveTo( ( window.screen.availWidth - giWidth ) / 2, ( window.screen.availHeight - giHeight ) / 2 );

oDOM = new ActiveXObject("Microsoft.XMLDOM");
oDOM.async = false;
oDOM.loadXML( oXMLDATA.innerHTML );
instantReport();
} catch(e) {
alert( "Your OS is missing components or they are disabled for processing XML data!\nDESC: " + e.description );
}
}

Notice in this case the code creates the xml document object and loads part of the 'HTML' in...

And here is another sample:


function saveSelf() {
var oFSO = new ActiveXObject("Scripting.FileSystemObject");
var oTempFile = oFSO.OpenTextFile( "xLinks.XML.hta", 1 );
var sSelfSource = String( oTempFile.ReadAll() );

var oPAGEARRAY = sSelfSource.split( '<meta' + ' val="2345"/>' );

var sNewSource = oPAGEARRAY[0] + '<meta' + ' val="2345"/> <xml id="oXMLDATA"> ' + oDOM.xml + ';</xml><meta' + ' val="2345"/> ' + oPAGEARRAY[2]

var oSDOM = new ActiveXObject("Microsoft.XMLDOM");
oSDOM.async = false;
oSDOM.loadXML( sNewSource );

if( oSDOM.xml != "" ) {
var oNewFile = oFSO.CreateTextFile( "xLinks.XML.hta", 1 );
oNewFile.WriteLine( oSDOM.xml );
oNewFile.close();
oNewFile = null;
alert( "Save Success!" );
window.close();
} else {
alert( "Save Operation Failed!" );
}
}

This function creates a File System Object. The trick here is basically the file runs as an HTA i.e. executable but then loads itself as a xml file or custom xml data base and updates 'records' in itself and overwrites itself. Now the trick here is that your HTML must be XML complaint. Really if you don't know what this means maybe you should start somewhere else before reading about how to hurt yourself with this stuff... :)

Monday, December 7, 2009

Hacking the Silverlight Xap file

Every now and then I find I need to pull resources out of a Xap file. One of the issues with this is knowing what’s in the XAP. There have been a number of solutions I’ve used over the years (ok that is like 2.5 ish years) like having an index file either a Csv or Xml etc. A few weeks ago I ran across this little class that some guys were talking about on the Silverlight Insiders/MVP thread called un-zipper found here:

http://www.sharpgis.net/post/2009/04/21/REALLY-small-unzip-utility-for-Silverlight.aspx

What is cool about this class is it makes getting the assets out of a zap even if you don’t know what is in the xap up front easy and straight forward. From a using standpoint you basically need to create a webclient and a call and use the Unzipper to run through the contents. The Unzipper class deals with mucking up what is in the xap so all you need to-do is run through the collection and pull out what you need… Let us take a look at what you need to-do:
Assuming you have the Unzipper class (download here) you need the following libraries:

using System.Collections.ObjectModel;
using System.Net;
using System.Windows.Controls;

From here we need to create a web client

WebClient wc = new WebClient();
wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
wc.OpenReadAsync(new Uri("HackingXaps.xap", UriKind.RelativeOrAbsolute));


In this code we create the WebClient, add a handler and run the call pointed at our xap we want to load.

void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error == null)
{
UnZipper unzip = new UnZipper(e.Result);

foreach (string filename in unzip.GetFileNamesInZip())
{
//do something with the file name…?
}
}
}

From here you can pretty much do whatever you want. Look to see this in the up coming version of the HackingSilverlight library.