How to make Silverlight be AiR?

27 באפריל 2008

[This blog was migrated. You will not be able to comment here.
The new URL of this post is http://khason.net/blog/how-to-make-silverlight-be-air/]


Today we’ll speak about three issues

  1. How to make Silverlight application to run as stand alone application and how to insert this application inside your application?
  2. How to escape Silverlight from it’s sand box (how to make it run in full trust mode)
  3. When first two items done, how to make Silverlight to access anyfile in your file system?

Looks scary? Let’s see first reasons for those “hackery” targets. The main reason is to make Silverlight Air (you, probably understand what I’m speaking about :)). Why? When I want to build Silverlight Image Upload control. The one similar to those Yahoo, Facebook and many others have. With live preview, editing (before uploading), drag and drop, etc. Yes, I do not want ugly File Open dialog from Silverlight. I want it sexy, yet functional! To do this, we have to make Silverlight be able to access filesystem. Of cause I want to ask user to authorize me first, then I can get an access.

image

The other reason is to incorporate Silverlight control inside WinForms application. Why? There are some reasons – “light weigh stuff”, maybe :). Maybe banner ads inside desktop application. It’s just cool :). Well, there are some other more serious reasons. So let’s start.

First task – to make it run as stand alone application.

Well, this one is easy. All you have to do is to have WebBrowser control with Silverlight content inside it in your application. So,

WebBrowser wb = new WebBrowser();
wb.Parent = panel1;
wb.Dock = DockStyle.Fill;
wb.Url = new Uri("http://0x15.net/play/SLFindResource/SLFindResource.html");

We done. But we’re in desktop, thus I want it full trust… This is most interesting part of today’s post.

Second task – to make it run in User Full Trust mode.

First try – to incorporate Silverlight’s OCX (ActiveX) control. Add npctrl.dll from [Program Files]\Microsoft Silverlight\[Version] – this is ActiveX and Visual Studio will create wrapper with AxHost. This one is cool, but it wont work. why? As you, probably, know Silverlight connected to it’s web page host DOM when we’re using it as stand alone player it cannot find it’s document, thus initialization failed. So what to do? What can provide me DOM from one side and run in full trust from the other side. Someone remember what HTA is (it is not mobile device, it’s very beginning of RIA era). HTML applications were run by very special host, named mshta.exe it’s in [Windows]\System32 folder and it’s still there. Everything running inside MSHTA will run by default in full trust mode. From one hand it’s regular IE, (do we have DOM), from other hand it’s make us able to run full trust internet application. Let’s use it (from code)

ProcessStartInfo mshta = new ProcessStartInfo("mshta", "http://0x15.net/play/SLFindResource/SLFindResource.html");
Process p = Process.Start(mshta);

Now we have strange window, running our Silverlight application. What’s next? Incorporate it inside our application. What’s the problem p (my process).MainWindowHandle and then SetParent for to the control I want. Well, it does not work. MSHTA has no (publicly) main window. So, we’ll find it and then change it’s parent. His class named “HTML Application Host Window Class”.

LockWindowUpdate(GetDesktopWindow());
ProcessStartInfo mshta = new ProcessStartInfo("mshta", "http://0x15.net/play/SLFindResource/SLFindResource.html");
Process p = Process.Start(mshta);
p.WaitForInputIdle();
ptr = FindWindow("HTML Application Host Window Class", null);

SetParent(ptr, panel1.Handle);
SendMessage(ptr, WM_SYSCOMMAND, SC_MAXIMIZE, 0);

LockWindowUpdate(IntPtr.Zero);

Yu-hoo. We hosted Silverlight page inside our application. It’s full trust so, we can access file system. But wait… Silverlight is not designed to have an access to the file system. The only space it can see is isolated storage, thus it has no classes for listing files anywhere. what to do?

Third task – to make it access user’s file system

We need another ActiveX to run from Javascript (or C# code) that knows to access to file system. Our hosting document can initialize it and then expose relevant methods to Silverlight. What’s such class? Let’s back to gold era of unsafe computing – we have Scripting.FileSystemObject there. This class is very dangerous it can do anything in local file system. Many system administrators using this class to script their evil login scripts (those black quick command line promps, that doing something bad to your system each time you’re logging in in your domain). It know everything about your disks and can be run from full trust environment. So, it’s just exactly what we need. Get all drives in your machine

drivetypes = [ 'Unknown', 'Removable', 'Fixed', 'Network', 'CD-ROM', 'RAM Disk' ],
driveprops = [ 'DriveLetter', 'DriveType', 'ShareName', 'IsReady', 'Path', 'RootFolder', 'FileSystem', 'SerialNumber', 'VolumeName', 'TotalSize', 'AvailableSpace', 'FreeSpace' ];

function getdrives() {
var fso = new ActiveXObject( 'Scripting.FileSystemObject' ),
  e = new Enumerator(fso.Drives),
  add = function(i) {
   i = driveprops[i];
   var prop = f[i];
   if( ( prop || prop===0 || prop===false ) && ( i!=='AvailableSpace' || prop!==free ) ) {
    if( /(Type)$/.test( i ) ) { prop = drivetypes[ prop ]; }
    if( /(Size|Space)$/.test( i ) ) { prop = bykb( prop, true ); }
    s.push( i.toCamelCase() + ':\t' + ( i.length < 8 ? '\t' : " ) + prop );
   }
  },

Then folders

function getfolder( s ) { s = trim( s ) || 'C:';
var fso = new ActiveXObject( 'Scripting.FileSystemObject' ),
  e, f, i, r = [];
if( fso.FolderExists( s ) ) {
  f = fso.GetFolder( s );
  e = new Enumerator(f.SubFolders);
  for( ; !e.atEnd(); e.moveNext() ) {
   if( ( i = e.item() ) ) { r.push( ' ' + i ); }
  }
  e = new Enumerator(f.files);
  for( ; !e.atEnd(); e.moveNext() ) {
   if( ( i = e.item() ) ) { r.push( " + i ); }
  }
}
return r;
}

And files at the end

function getfile( form ) {
var fso = new ActiveXObject( 'Scripting.FileSystemObject' ),
  forReading = 1, forWriting = 2, forAppending = 8,
  dd = function( o, s ) {
   try {
    s = f[s] + ";
    o.value = s.replace( /^(\w{3}) (\w+) (\d\d?) ([\d:]+) ([\w+]+) (\d+)$/, '$3 $2 $6 $4' );
   } catch(e) {
    o.value = e.message;
   }
  },

Very cool we have files by using f = fso.GetFile( name ); method, now we can do anything with it. For example get or set attributes f.attributes, or rename f.Name = s, or, even delete it f.Delete(); Isn’t it really evil?

We done. Now you can run Silverlight as full trust desktop application and, even host it wherever you want. Even inside calculator…

ProcessStartInfo calc = new ProcessStartInfo("calc");
using (Process p = Process.Start(calc))
{
    p.WaitForInputIdle();
    SetParent(ptr, p.MainWindowHandle);
    SendMessage(ptr, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
    p.WaitForExit();
}

Happy programming and be good people.

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

14 תגובות

  1. Aaron Fischer27 באפריל 2008 ב 22:59

    You have broken the cross platform benefit. Your file io requires the full version of .net(now the user needs .net and silverlight) and worse yet you could have done all this with wpf via click once or xbap. So what was the point?

    הגב
  2. Tamir Khason28 באפריל 2008 ב 7:41

    Aaron, this article is about how it's possible to play with Silverlight. It does not make it better or something 🙂
    Regarding .NET – it is not nessesery to have .NET installed in the machine due to fact, that this sample uses regular win32 calls. I just used .NET to demonstrate it.
    Anyway, WPF it better 🙂

    הגב
  3. Aaron Fischer28 באפריל 2008 ב 16:50

    Sorry I miss read Scripting.FileSystemObject for System.IO namespace.

    הגב
  4. Laurent Bugnion30 באפריל 2008 ב 19:16

    Hi,

    Some days ago, I published a solution using a HTA. I am not quite sure, however, why you would host the HTA into a WinForms host. It seems overkill. HTA applications can run standalone, and using JavaScript to access the file system is possible, as JavaScript runs with elevated permissions in HTA.

    I recommend you to take a look at my solution, it is available here:
    http://blog.galasoft.ch/lbugnion/archive/2008/04/24/silverlight-running-standalone-full-trust-applications.aspx

    I'd love to discuss the advantages and inconveniencies of both solutions with you. Don't hesitate to contact me!

    Greetings,
    Laurent

    הגב
  5. Christophe Lauer [MS]30 באפריל 2008 ב 19:27

    Hey, I see that we're trying to play with the same kind of stuff.

    I also have a working sample of a very basic file explorer in Silverlight 1.0, but I chose to go another route.

    You're using an ActiveX object to gain filesystem access, which is not really the way it works in Adobe AIR.

    I think I mimiced the way things work in AIR by exposing APIs at the WindowsForms container application level, such as, I'm not depending on loading an ActiveX and I can wrap and expose any OS feature I wish (access to the registry, test which version of the OS I'm running, etc…)

    Would you be interested in me sharing this code?

    הגב
  6. Tamir Khason30 באפריל 2008 ב 19:44

    Laurent, MSHTA provides the ability to use Silverlight as stand alone application, however it does not solves the problem of hosting SL inside your own application. Thus I advice to use HTA as middleware platform, and not as stand alone application

    Christophe, once our application is running in full trust mode we can even invoke WIN32 methods to access FS. Sure It might be very interesting to see your work also

    הגב
  7. Laurent Bugnion30 באפריל 2008 ב 19:49

    Tamir,

    In that case, your silverlight application is not a standalone application 🙂 (granted, my solution is not standalone either, since it's hosted, but it's more standalone 🙂

    Very similar solutions anyway. It's kind of strange to see that solution coming from someone (two persons if I count Christophe) working for Microsoft. It's not very much in line with the feedback I got so far 🙂

    Greetings,
    Laurent

    הגב
  8. Christophe Lauer [MS]30 באפריל 2008 ב 21:02

    @Tamir : what is the feedback you got so far?

    I wrote this quick&dirty sample in order to share it with external Silverlight developers so that they can better understand the kind of features that AIR provides for Flash and Flex apps, without having to heavilly invest time on this platform.

    Mine was meant as a total stand-alone solution. The dirty part is that I embed the Cassini webserver assembly so that the WindowsForms container app can expose the Silverlight app to the WebBrowser object and that the user doesn't get prompted by security warnings when running scripts from the local filesystem.

    I expect future releases of the Silvelright stuff to provide automation APIs or equivalent that will allow for direct Silverlight plug-in integration into a native app, thus allowing me to get rid of this local webserver horror.

    At the same time, i could drop WindowsForms and the WebBrowser and switch to WebKit and try to get this multi-platform…

    הגב
  9. Tamir Khason30 באפריל 2008 ב 22:06

    Chrostophe, I think it might be problem from LCA to allow such integration. Silverlight plugin contains some patent protected technologies, thus it cannot be distributed anyway except directly from MS website. However your solution looks cool and might pass LCA.
    My customer was rather happy with MSHTA as host platform, however WebKit is really great idea – does it works?

    הגב
  10. Laurent Bugnion30 באפריל 2008 ב 23:08

    @Christophe: I am the one who mentioned MSFT's feedback. Officially, you guys are not looking into turning Silverlight into a standalone platform (I am a MVP and even under NDA, there was no communication in this direction).

    Make sure you check my HTA solution. If I could only get this to work on multi-platforms 🙂

    http://blog.galasoft.ch/lbugnion/archive/2008/04/24/silverlight-running-standalone-full-trust-applications.aspx

    Laurent

    הגב
  11. Christophe Lauer [MS]30 באפריל 2008 ב 23:56

    @Laurent : Ok, got it, and I can confirm to you all folks that as of today, we don't have a public commitment to produce a kind of AIR container for Silverlight to enable RIA on the desktop.

    My stuff is just a lame "proof of concept", nothing more… just not to shift expectations 🙂

    הגב
  12. kenn13 באוגוסט 2008 ב 4:47

    in the line:

    ptr = FindWindow("HTML Application Host Window Class", null);

    how can you be sure that you found the right MSHTA as opposed to some other one that happens to be running?

    הגב
  13. MY14 בנובמבר 2008 ב 18:45

    How can I use this application to create, in essence, an HTML with links to pdfs and ppts? I don't want the toolbar to show in the initial page (autorun from CD). I just want it to load on a fixed window size with no toolbars so the user isn't tempted to navigate (wonder) away. I can do this with "hta" but only on PC with IE 5 or greater. I need it to work cross-platforms and cross-browsers. Thank you.

    הגב
  14. steve25 בנובמבר 2008 ב 16:22

    Great job. This will help push Microsoft to release a Fit Client platform for Silveright. I'm gonna use this until then. Keep it up!

    הגב