Chris's coding blog

Creating a custom silverlight installation the jQuery way

November 11, 2010

The default Silverlight installation and upgrade experience is fairly jarring compared to its counter-part Flash. If you target version 4.0 of Silverlight and the user has 3.0 installed, they will receive an ugly and annoying modal dialog forcing them to upgrade.

If they don’t have Silverlight installed, they simply get a big button that leads them into Microsoft’s corporatey and fairly none-consumer friendly Silverlight page.

As well as the unfriendly installation, the upgrade path is fairly unintuitive too, atleast in regards to the HTML tags. The parameter is there to allow you to handle upgrading yourself, however what the Silverlight FAQ fails to tell you is if you set this parameter to false, you must handle the upgrade and installation using the Silverlight Javascript API.

There is a whitepaper and Microsoft do recommend creating your own installation process. It makes your app look more professional doing this way - the example below has taken this example, fixed the typo in the code, given it a sprinkle of jQuery and updated it for Version 4.

You may get upgrade problems (which I got going from Silverlight 3) where onUpgradeRequired is not being called, and instead onSilverlightError gets called with:

Error: Unhandled Error in Silverlight
Application Code: 8001
Category: InitializeError
Message: 8001
An error has occurred.

The solution I found to this was to stick the following at the top of the onSilverlightError function:

if (args.ErrorCode.toString().indexOf("8001") > -1)
{
	showState("#upgrade-start");
	return;
}

This may also occur with a 8002 error if the user hasn’t restarted the browser after an upgrade.

If you want to test with old versions of Silverlight, it’s best to use a Windows XP VM image, and download versions 1-4 from oldapps.com.

The entire solution including the XAP and JS files can be downloaded here.

<html>
<head>
<title>Silverlight Installation example</title>
<style type="text/css">
body { background:#FFFFFF;font-family:Verdana,sans-serif;text-align:center;}
h1 { font-size:1.2em;}
#install-container
{
background: #ABABAB;
width:500px;
height:500px;
border:2px solid green;
margin: 0 auto;
padding:10px;
color:#FFFFFF;
margin-top:20px;
border-radius: 15px;
}
.content { text-align:left;padding:10px;height:300px;margin-top:20px;}
.hidden { display:none; }
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript"></script>
<script src="Silverlight.js" type="text/javascript"></script>
<script src="Silverlight.supportedUserAgent.js" type="text/javascript"></script>
<!-- Silverlight error script -->
<script type="text/javascript">
function onSilverlightError(sender, args)
{
// A work around for upgrade issues
if (args.ErrorCode.toString().indexOf("8001") > -1)
{
showState("#upgrade-start");
return;
}
if (args.ErrorCode.toString().indexOf("8002") > -1) {
showState("#restart-pending");
return;
}
if (Silverlight.IsVersionAvailableOnError(sender, args))
{
var appSource = "";
if (sender != null && sender != 0) {
appSource = sender.getHost().Source;
}
var errorType = args.ErrorType;
var iErrorCode = args.ErrorCode;
var errMsg = "Unhandled Error in Silverlight Application " + appSource + "\n";
errMsg += "Code: " + iErrorCode + " \n";
errMsg += "Category: " + errorType + " \n";
errMsg += "Message: " + args.ErrorMessage + " \n";
if (errorType == "ParserError") {
errMsg += "File: " + args.xamlFile + " \n";
errMsg += "Line: " + args.lineNumber + " \n";
errMsg += "Position: " + args.charPosition + " \n";
}
else if (errorType == "RuntimeError") {
if (args.lineNumber != 0) {
errMsg += "Line: " + args.lineNumber + " \n";
errMsg += "Position: " + args.charPosition + " \n";
}
errMsg += "MethodName: " + args.methodName + " \n";
}
throw new Error(errMsg);
}
}
</script>
<script type="text/javascript">
$(document).ready(function()
{
if (Silverlight.supportedUserAgent())
{
$("#install-start a").click(function()
{
$("#install-start").toggle();
$("#install-complete").toggle();
window.location = "http://go2.microsoft.com/fwlink/?linkid=124807";
});
$("#upgrade-start a").click(function()
{
$("#upgrade-start").toggle();
$("#upgrade-complete").toggle();
window.location = "http://go2.microsoft.com/fwlink/?linkid=124807";
});
$("#restart-pending a").click(function()
{
$("#install-container").hide();
$("#silverlightControlHost").show();
});
}
else
{
showState("#not-supported");
}
});
function onSilverlightLoad(sender)
{
Silverlight.IsVersionAvailableOnLoad(sender);
}
Silverlight.onRestartRequired = function()
{
if (Silverlight.supportedUserAgent())
showState("#restart-pending");
};
Silverlight.onUpgradeRequired = function()
{
if (Silverlight.supportedUserAgent())
showState("#upgrade-start");
};
Silverlight.onInstallRequired = function()
{
if (Silverlight.supportedUserAgent())
showState("#install-start");
};
function showState(id)
{
$("#silverlightControlHost").hide();
$("#install-container").show();
$(id).toggle();
}
</script>
</head>
<body>
<div id="install-container" class="hidden">
<div class="content">
<!-- No silverlight installed -->
<div id="install-start" class="hidden">
<h1>You need to install Silverlight</h1>
<a href="javascript:;">Click here to install it.</a>
</div>
<!-- Install pending or completed -->
<div id="install-complete" class="hidden">
<h1>Installing Silverlight...</h1>
Please restart your browser once the installation is complete.
</div>
<!-- Upgrade starting -->
<div id="upgrade-start" class="hidden">
<h1>You need to upgrade Silverlight</h1>
You to upgrade the Silverlight plugin before you continue.
<a href="javascript:;">Click here to upgrade it.</a>
</div>
<!-- Upgrade pending or complete -->
<div id="upgrade-complete" class="hidden">
<h1>Upgrading Silverlight...</h1>
Please restart your browser once the upgrade is complete.
</div>
<!-- Restart required -->
<div id="restart-pending" class="hidden">
<h1>Please restart your browser before continuing.</h1>
If you have already restarted your browser, <a href="javascript:;">click here</a> to continue.
</div>
<!-- Not supported -->
<div id="not-supported" class="hidden">
<h1>Sorry, your browser does not yet support Microsoft Silverlight.</h1>
Silverlight is currently supported on the following browsers:
<ul>
<li>Microsoft Internet Explorer</li>
<li>Mozilla Firefox 3+ (Windows and Mac OS X)</li>
<li>Google Chrome (Windows)</li>
<li>Safari (Mac OS X)</li>
</ul>
Please use one of the browsers above to be to enable the enhanced editor.
</div>
</div>
</div>
<div id="silverlightControlHost" style="height:100%;">
<object data="data:application/x-silverlight," type="application/x-silverlight" width="100%" height="100%">
<param name="source" value="Silverlightsniffing.xap"/>
<param name="background" value="white" />
<param name="minRuntimeVersion" value="4.0" />
<param name="autoUpgrade" value="false" />
<param name="onerror" value="onSilverlightError" />
<param name="onload" value="onSilverlightLoad" />
</object>
<iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>
</div>
</body>
</html>
view raw gistfile1.html hosted with ❤ by GitHub

silverlight

I'm Chris Small, a software engineer working in London. This is my tech blog. Find out more about me via GithubStackoverflowResume