Piotr Puszkiewicz's Silverlight Blog

  • Silverlight.js available on MSDN Code Gallery

    Silverlight.js is now available for download on MSDN Code Gallery via http://code.msdn.microsoft.com/silverlightjs. Silverlight 1.0 and Silverlight 2 Web sites can use this updated file to add support for Firefox 3 and to enable new features such as an automatic browser refresh when Silverlight installation is complete.

    Since this latest version of Silverlight.js introduced a number of breaking changes, you will want to review the readme for tips and workarounds.

    We also released a Sivlerlight.js add-on file for Web sites that want to determine if the user's browser is supported by Silverlight. This file brings back the Silverlight.supportedUserAgent functionality that was present in the 1.0 version of Silverlight.js. Since user agent identification is very fragile, you should only use this file if you want to verify that a user agent explicitly identifies itself as a supported platform per the Silverlight System Requirements page. This add-on file is called Silverlight.supportedUserAgent.js and can be obtained from http://code.msdn.microsoft.com/SLsupportedUA.

  • What's new in the Silverlight 2 Beta 2 SDK's Silverlight.js file?

    The Silverlight.js file was updated with several important improvements in the Silverlight 2 Beta 2 SDK. These improvements were focused on two key areas: better experiences out-of-the-box for end users and easier customization of those experiences for developers. To these ends we added functionality that was frequently implemented on Silverlight web sites, we fixed known bugs, and we removed Silverlight 1.0-functionality which did not add value in Silverlight 2. The updated file is also designed with <object> tag instantiation in mind, making interactions between Silverlight.js and <object> tags easier than ever.

    Better End-User Experience

    When you use the Silverlight.createObject function to instantiate the Silverlight control on your web page there is a default prompt that is displayed to users who do not have the right version of Silverlight installed. In Silverlight 1.0 the default prompt looked like this:

     sl1indirectinstallmedallion

    Clicking on this image linked to www.microsoft.com/silverlight/install.aspx. A user would visit the Silverlight Web site, install the control, and return to the originating Web site to view the content.

    We improved this model for the end user through better UI, reduced clicks during installation, and automatic content loading.

    Improved UI

    We updated the graphic that is displayed so that it is better at integrating with a wide range of Web sites:


    As you can see, this graphic ( it is the same png on all three backgrounds) has a transparent border which helps blend the site's background color with the installation image. It even works over top of other images, thereby giving users an integrated feeling without any additional work on the part of the developer.

    Reduced installation clicks

    We reduced clicks by pointing the hyperlink associated with this image directly to the Silverlight installer. Therefore, instead of visiting Microsoft.com, installing, and returning, the user now clicks on the image and installs Silverlight without ever leaving the page.

    Automatic Content Loading

    Once the user finishes installing something needs to happen to let them see Silverlight content. In 1.0 that something was either a browser refresh or a browser restart, depending on the browser. I have recently blogged about avoiding both of these experiences through script. This behavior has been added to Silverlight.js and is on by default. Therefore, any page which references the new Silverlight.js file will get the auto-refresh behavior, where available.

    Better Developer Experience

    All of the new user experience functionality was implemented with the developer in mind. Therefore, we have introduced a number of new events, methods, and properties to help customize any portion of the installation experience.

    Improved UI

    While the new install prompt image is designed to work with a large variety of sites, we understand that it may not be sufficient for all scenarios. Therefore, a developer can now pass an alt parameter to Silverlight.createObject. The value of this parameter should be a chunk of valid HTML encoded as a javascript string. If the createObject method finds that the Silverlight control is not available then it will load this HTML instead of the default image displayed above.

    Reduced Installation Clicks

    For the alt HTML to be useful it must know how to start the download of the Silverlight installer. To help with this, we added the Silverlight.GetSilverlight method. When this method is called it determines which installer link to use and navigates the browser to that link. In most cases, this will lead directly to the installer and therefore keep the user on the current page.

    Automatic Content Loading

    By default, including the Silverlight 2 Beta 2 version of Silverlight.js in a web page will cause the file to detect if a user has any version of Silverlight installed. If the user does not then an installation monitoring process, Silverlight.WaitForInstallCompletion, is started. This process will occasionally check to see if Silverlight has been installed. Once it detects that installation is complete it will refresh the page so that the user has immediate access to the page's Silverlight content without any additional user action.

    If a web author does not like the refresh experience then this process can be disabled by setting the value of Silverlight.onSilverlightInstalled to null. Silverlight.onSilverlightInstalled is treated as an event handler and will be called when Silverlight.WaitForInstallCompletion detects that installation is complete. This can be used to enable more interesting installation scenarios. For example, a dev could set Silverlight.onSilverlightInstalled to a function which dynamically injects Silverlight object tags into a page, thus avoiding a browser refresh all together.

    onSilverlightInstalled can also be combined with another new Silverlight.js event, SilverlightonGetSilverlight, to give users a guided installation experience. Silverlight.onGetSilverlight gets called whenever someone calls Silverlight.GetSilverlight. This should happen whenever the user clicks a button which starts the Silverlight installation process. Therefore, a site author can have a DIV which tells the user to "install Silverlight".  When the user clicks the installation button, that click causes a call to Silverlight.GetSilverlight --> Silverlight.onGetSilverlight. When Silverlight.onGetSilverlight is called, it can change the contents of the DIV to "Silverlight is installing. Make sure you approve the installation." Once the user finishes installing Silverlight, Silverlight.onSilverlightInstalled is called. This can change the DIV to say "Thank you for installing Silverlight. <Name of your app> is loading..." and set a timeout which then dynamically injects a Silverlight <object> tag in a few seconds.

    New Members

    Silverlight.onSilverlightInstalled Event

    Occurs when the Silverlight plug-in has finished installing

    Scripting (Runtime) Silverlight.onSilverlightInstalled = functionName;
    Event Handler Parameters

    The event handler should expect no parameters.

    Remarks

    The onSilverlightInstalled event occurs after a user finishes installing the Silverlight plug-in on a machine without a previous version of Silverlight. The event will not fire if the user is upgrading from a previous version.

    By default, onSilverlightInstalled is set to a function which refreshes the browser on the current page. If this is not the desired behavior then onSilverlightInstalled should be set to null or another javascript function during the page's OnLoad event.

    Silverlight.WaitForInstallCompletion

    Triggers Silverlight.onSilverlightInstalled event when Silverlight is installed.

    Silverlight.isBrowserRestartRequired

    Boolean value set at page load time. If true then any upgrade of the Silverlight control will require a browser restart. Otherwise, onSilverlightInstalled will be triggered when installation is complete.

    Silverlight.GetSilverlight

    Begins the Silverlight installer download process.

    Scripting

    Silverlight.GetSilverlight(versionString);
    Parameters

    versionString

    string

    A string that represents the requested version of Silverlight. See Silverlight Versioning.
    Return Value

    None.

    Remarks

    The method will generate and follow the Silverlight installation URL appropriate for the requested Silverlight version. This will typically result in the Silverlight installer being downloaded without navigating away from the current web page. The user will only be navigated away from the web page if they are found to be using an unsupported platform. If that is the case, they will be brought to a Microsoft Web site which will help them understand the problem.

    Silverlight.onGetSilverlight Event

    Occurs when Silverlight.GetSilverlight is called. Enables developers to capture click events on the Silverlight installation image without modifying the default image.

    Scripting (Runtime) Silverlight.onSilverlightInstalled = functionName;
    Event Handler Parameters

    The event handler should expect no parameters.

    Remarks

    Some browsers block unintended file downloads by mapping download requests to user actions. If the handler for onGetSivlerlight clicked takes too much time to return then the browser may block the download. Therefore it is very important for the onGetSilverlight handler to avoid performing long-running operations unless they are started asynchronously. Long-running operations can be started asynchronously by using the setTimeout method.

    Silverlight.createObject alt Parameter

    Defines alternate HTML to use when an appropriate version of Silverlight is not available.

    Usage
        var altHTML = "<a href='javascript:Silverlight.getSilverlight(\"{1}\");' style='text-decoration: none;'>"+
    "<img src='{2}' alt='Get Microsoft Silverlight' style='border-style: none'/></a>";

    Silverlight.createObject( "plugin.xaml", // Source property value. parentElement, // DOM reference to hosting DIV tag. "myPlugin", // Unique plug-in ID value. { // Plug-in properties. width:'1024', // Width of rectangular region of plug-in in pixels. height:'530', // Height of rectangular region of plug-in in pixels. background:'white', // Background color of plug-in. isWindowless:'false', // Determines whether to display plug-in in windowless mode. framerate:'24', // MaxFrameRate property value. version:'1.0' // Silverlight version.
    alt: altHTML // Alternate HTML to display if Silveright is not installed }, { onError:null, // OnError property value -- event-handler function name. onLoad:null // OnLoad property value -- event-handler function name. }, null, // initParams -- user-settable string for information passing. null); // Context value -- passed to Silverlight.js onLoad event handlers.
    Remarks

    Be sure to call Silverlight.getSilverlight to initiate the installation process.

    Fixes

    The Silverlight 2 Beta 2 version of the Silverlight.js file fixes a known issue in the Silverlight.isInstalled method. You can learn about the fix here: Firefox 3 support added to Silverlight 2 Beta 2 SDK's Silverlight.js.

    Removed Members

    The following members were removed from Silverlight.js. These members were previously used to determine the browser type that the client was using and to offer correct installation experiences for each browser type. This updated version of the file has removed its dependencies on specific browsers and instead relies on features common to the IE and Mozilla browser families. The primary usage scenarios for these members was to determine if the user should be asked to restart their browser after they start the installation process. However, this scenario can now be implemented in a more reliable fashion by checking if(Silverlight.isBrowserRestartRequired) in their handler for Silverlight.onGetSilverlight.

    • Silverlight.ua
    • Silverlight.available
    • Silverlight.detectUserAgent
    • Silverlight.supportedUserAgent
  • Structure of the Silverlight Object Tag

    The Silverlight 2 installation/instantiation model promotes the use of the Silverlight <object> tag template. In my post Instantiating Silverlight: HTML vs. Script I mentioned that this template was designed to meet five criteria:

    1. be backwards-compatible with Silverilght 1.0
    2. rely on static HTML only
    3. offer the right installer for the right client (Mac vs. Windows vs. other)
    4. provide actionable feedback to users who will not be able to use Silverlight
    5. provide an easily-customizable installation/upgrade experience

    This post will provide detail around how each of these criteria is met by the template.

    <object data="data:application/x-silverlight," type="application/x-silverlight-2-b2" width="500" height="500">
        <param name="source" value="MyApplication.xap"/>
        <param name="onerror" value="myOnError" />
        <param name="background" value="black" />
        
        <a href="http://go.microsoft.com/fwlink/?LinkID=115261" style="text-decoration: none;">
             <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" 
    style="border-style: none"/> </a> </object> <iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>

    Example 1: Silverlight 2 Beta 2 <object> template (partial)

    Compatible with Silverlight 1.0

    The Silverlight 1.0 installation and instantiation model was built around a javascript helper file called Silverlight.js. This file takes a set of parameters via a function and uses the parameters to inject a Silverlight control into a <DIV> on the web page. The Silverlight control is injected into the <DIV> by means of an <object> tag on IE and an <embed> tag on Firefox and Safari.

    By using just the MIME type in the <object> tag and not the classid, a web page is able to correctly instantiate the Silverlight control across all browsers that are supported by Silverlight. The type attribute which specifies the MIME type is interpreted in the same fashion by these browsers while the classid attribute has differing, and often mutually exclusive, definitions. Therefore, using the type attribute in an <object> tag is sufficient for instantiating Silverlight 1.0 and Silverlight 2 controls through the use of a single HTML tag.

    <object ... type="application/x-silverlight-2-b2" ...>

    Rely on Static HTML Only

    Removing the js dependency present in the Silverlight.js model was important in a number of hosting scenarios:

    1. Some web hosts do not allow users to add javascript to their web pages
    2. Linking an application in a web page requires the author to link both the application and the Silverlight.js file
    3. Browsers with javascript disabled are not able to view Silverlight content

    Once we settled on using a single <object> tag, the static HTML instantiation model was readily available. However, 1.0 also relied on Silverlight.js to inject the Silverlight installation prompt when the right version of the control was not already installed on the user's computer. Providing this same experience in an <object> tag is done by using the browser's fallback mechanism for object tags. Specifically, if a web browser encounters an <object> tag with a MIME type that it does not recognize then the browser will ignore the <object> tag and any associated<param> tags. Instead, it will render the inner HTML of the <object> tag. Therefore, given the following block of HTML:

    <object type="fake/mimetype" width="500" height="500">
        <param name="foo" value="bar"/>
        
        <table>
            <tr>
                <td>
                    You need the control to view this content!
                </td>
                <td>
                    <a href="http://www.tempuri.org/install/control.exe">
                        <img src="http://www.tempuri.org/install/installControl.png" alt="Install Control"/>
                    </a>
                </td>
            </tr>
        </table>
    </object>

    If the browser has a control mapped to the "fake/mimetype" MIME type then it will treat this block as:

    <object type="fake/mimetype" width="500" height="500">
        <param name="foo" value="bar"/>
    </object>

    Otherwise, it will ignore the <object> and <param> tags and treat the block as:

    <table>
        <tr>
            <td>
                You need the control to view this content!
            </td>
            <td>
                <a href="http://www.tempuri.org/install/control.exe">
                    <img src="http://www.tempuri.org/install/installControl.png" alt="Install Control"/>
                </a>
            </td>
        </tr>
    </table>

    The Silverlight <object> template uses this fallback mechanism to display installation content when Silverlight is not available. If the user visits a Silverlight-enabled web page and has Silverlight installed then the Silverlight application is shown. If the user does not have Silverlight installed then the browser will ignore the Silverlight <object> tag and display the inner HTML. By default, the following HTML is used for Silverlight 2 Beta 2:

    <a href="http://go.microsoft.com/fwlink/?LinkID=115261" style="text-decoration: none;">
         <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" 
    style="border-style: none"/> </a>

    And, when rendered, generates this UI element:

    Get Microsoft Silverlight

    Offer the right installer for the right client

    If you inspect the default installation HTML for the Silverlight <object> template you will notice that it uses a single <a> tag to refer to the Silverlight installer: http://go.microsoft.com/fwlink/?LinkID=115261 for Silverlight 2 Beta 2. In the Silverlight.js file, however, there was a unique URL for each OS version of the installer: .exe for Windows, .dmg for Mac, and a separate URL for unsupported platforms. In Silverlight 2 Microsoft moved this detection logic to the server side. When a user follows the aforementioned installer URL a server process determines if an applicable installer exists for that user. If so, they are given that installer without ever leaving the page they were trying to view. If the browser is not supported by Silverlight, like 64-bit IE, then they are redirected to a Microsoft Web page which tells them about the platform requirements of the Silverlight control.

    This server-side tool is useful for a number of reasons. First, a web site only needs to offer a single download URL for the control. Second, web authors don't have to worry about communicating problematic conditions, like unsupported platforms, to the end-user. Third, if a platform moves from the unsupported list to the supported list then Web sites using this single URL will usually get support for that platform automatically.

    Provide actionable feedback to users

    This was covered a bit in the previous section. There is a set of users for whom we can detect that Silverlight will not work well under their current system configuration. The three big groups in this set are:

    • Unsupported OS
    • Unsupported Browser
    • Unsupported Browser Flavor (64-bit IE)

    The system which decides which installer to offer for a particular client also checks for these conditions. If any of them are met then the user is sent to a Microsoft Web page which tells them about the detected problem. In some cases, the system tells users that their OS is unsupported. In other cases, the user is warned that they should switch to a supported browser. In the 64-bit browser case, the user is asked to use a 32-bit browser instead.

    This system will be updated with new error conditions as they become problematic. The goal of this system is to, as much as possible, prevent users from getting into infinite installation loops. We chose this particular implementation because it moves the responsibility of detecting problematic conditions to Microsoft and away from Web site owners.

    Provide an easily-customizable installation/upgrade experience

    While the default installation medallion for Silverlight is very clear and actionable, it does not provide insight into the cool features of the Silverlight-powered application that is asking for the install. The Silverlight <object> tag template is easily customizable so that this insight can be provided at a very low cost. Instead of writing Javascript, a developer can simply take ordinary HTML code from a designer and add it to their Silverlight <object> tag template. As long as this HTML contains a link to the Silverlight installer and is wholly contained by the associated Silverlight <object> tag, it will provide a customized installation experience. You can see an example of this in the "Rely on static HTML only" section above.

    Other template elements

    data="data:...,"

    There are two elements of the <object> tag template whose purpose is not immediately clear. The data attribute of the <object> tag and the trailing <iframe> tag.

    The data attribute was added to the Silverlight <object> tag shortly before Silverlight 1.0 shipped. The attribute was added to augment a behavior we were seeing in some Silverlight-supported browsers. If we added an <object> tag to a web page and did not include a data attribute on that <object> tag then the browser would pass the html file which contained the <object> tag to the object through the data field. I'll clarify with an example:

    test1.html
    ---------------------------------------------------
    <html>
       <body>
           <object type="fake/MIMEtype">
           </object>
       </body>
    </html>
    ---------------------------------------------------

    When read by particular browsers, this web page would be treated like this:

    test1.html (example of strange behavior)
    ---------------------------------------------------
    <html>
       <body>
           <object type="fake/MIMEtype" data='<html><body><object type="fake/MIMEtype"></object></body></html>'>
           </object>
       </body>
    </html>
    ---------------------------------------------------

    This behavior obviously increases the memory footprint of the affected control, especially for complicated web pages. What is worse, the HTML for the web page was not retrieved from memory. Instead, the browser would make additional requests back to the Web server to get updated copies of the page. This added latency to page load times and increased the server load for these web pages.

    To mitigate the problem, we needed a cross-browser method for populating the <object>'s data attribute without adding cost for the web developer. After some research we found that the object tag specification allows for data to be specified externally (from a file) or inlined (from HTML). With this in mind, we created the data attribute to be an inlined empty data stream which would not be associated with any other control. The result is what you have seen:

    data="data:application/x-silverlight,"

    The Silverlight MIME type prevents other controls from interpreting this data incorrectly. The empty string after the comma minimizes the size of the stream. Adding this attribute to <object> tags prevents extra memory usage and server hits.

    <iframe>

    The trailing <iframe> is included to provide a consistent caching experience across browsers. According to the Safari Developer FAQ, "Safari achieves much of its performance through efficient use of content caching." This caching can provide inconsistent behavior for Silverlight controls that are rendered in Safari and the same controls rendered by other browsers. For example, the behavior of onLoad events may become different from what is expected. To ensure that Silverlight content behaves in a predictable fashion, we included the <iframe> tag as suggested by the Safari Developer FAQ. That same FAQ, however, offers a number of alternatives to the <iframe> which a developer may choose to implement instead.

  • Instantiating Silverlight: HTML vs. Script

    Many Silverlight developers have noticed a rather fundamental change between the Silverlight installation/instantiation models in Silverlight 1.0 and Silverlight 2.0. Silverlight 1.0 relied on a javascript helper file, Silverlight.js, to provide the installation experience for the control. Silverlight 2 projects and samples, however, have moved away from the Javascript model and towards a more familiar <object> tag model. This raises a few questions: Why Silverlight.js in 1.0? Why <object> in 2.0? And, most importantly, which model is right for me?

    Why Silverlight.js in 1.0?

    Many Silverlight 1.0 developers remember working with a helper file called Silverlight.js. At it's core, this file contained a function called Silverlight.createObject. When a page called on this function Silverlight.js determined if Silverlight was installed and, if so, would put a Silverlight control into a pre-defined <DIV>. This model provides many advantages to the developer. First and foremost, Silverlight 1.0 was a new product with a new <object> tag that was not well understood by most developers. By providing a helper function with named parameters we were able to help folks get accustomed to the Silverlight development model without having to build <object> tags by hand. Second was the installation experience. Silverlight.js provided a consistent cross-browser installation experience which did not depend on browser-specific installation technologies. Third was the selection of an installation binary. Silverlight 1.0 was offered for Windows, Intel Mac, and PPC Mac. By using Silverlight.js a developer could ignore the fact that they needed to choose an installer URL and could trust the js file to do the right thing when a user clicked the installation button. Finally, there was the utility functionality provided by Silverlight.js. Sites which wanted to provide specific experiences based on the installed version of Silverlight could do so through pre-defined javascript. Using javascript also helped Web sites remove the"Click To Activate" requirement in IE.

    Why <object> in 2.0?

    Despite the benefits of Silverlight.js, using the helper file requires active involvement on behalf of the Web site administrator. As the Web ecosystem changes over time Microsoft will have to continue updating the Silverlight.js file. When we do, web admins who want to take advantage of new functionality will need to download the latest version of the file, stage it, test their Web site, and deploy to production.

    In Silverlight 1.0 we wanted to provide a lighter-weight approach for Silverlight installation and instantiation which would give developers many of the benefits of Silverlight.js without requiring the maintenance costs of Silverlight.js. Specifically, we wanted a model which met the following criteria:

    1. be backwards-compatible with Silverilght 1.0
    2. rely on static HTML only
    3. offer the right installer for the right client (Mac vs. Windows vs. other)
    4. provide actionable feedback to users who will not be able to use Silverlight
    5. provide an easily-customizable installation/upgrade experience

    After several proposals and lots of testing we found that the <object> tag method, combined with several cool sever and control technologies, provided us with the ability to meet the requirements above in the most scalable fashion. I will get into the details of how this works in a future post, but here's a summary of what you get by using the <object> method:

    • Support for users with script disabled
    • Always up-to-date server-side user requirement detection:
      • do they want the Windows exe?
      • do they want the Mac dmg?
      • are they running in an unsupported mode (64-bit browser)?
      • Are they running on an unsupported platform?
    • Plain HTML install/upgrade experience development

    Which model is right for me?

    As you would expect, both models still exist because there are scenarios which are met by one and not the other.

    Use <object> tag if you want to add Silverlight to your site and not mess with related HTML or javascript again. Your users will be able to install, upgrade, and view Silverlight content without enabling javascript. Microsoft will provide your sites users with installers and error-resolution web content based on server-side detection. Your Web site will automatically work with new Silverlight platforms as they come online. Changes in browsers are unlikely to impact the functionality of your site because you are using simple HTML concepts and not script.

    Use Silverlight.js if you are actively maintaining your Silverlight content and want to have fine control over your users' experiences. You want to use script to provide specific javascript-driven experiences when Silverlight is not installed, when the installation button is clicked, when installation finishes, etc. You also want to be sure that users never see the "Click To Activate" experience in IE. Finally, you want to be able to refresh your web page when installation is finished. Since script is more likely to be affected by changes in the browser, be sure to check back often for changes/fixes in the released Silverlight.js file.

    Use a combination of models if you want the simplicity of <object> with the added benefit  of automatic page refresh on install. Simply include a <script type="text/javascript" src="[myPath]\Silverlight.js"></script> pointing to your copy of the Silverlight 2 Beta 2 SDK's Silverlight.js file to get this experience.

  • Firefox 3 support added to Silverlight 2 Beta 2 SDK's Silverlight.js

    Lots of folks are starting to notice that changes between Firefox 2 and Firefox 3 are causing failures in the isInstalled function used in older Silverlight.js files. Since the Silverlight.createObject function uses isInstalled, this results in Silverlight content being blocked on Firefox 3. Instead of seeing the content they expect, users are being asked to install Silverlight over and over again. The Silverlight 2 Beta 2 SDK offers an updated Silverlight.js file which includes an updated isInstalled method that covers the Firefox 3 scenario. To make your site Firefox 3 ready, download the new SDK and replace your existing Silverlight.js file with this updated version. Be sure to test your site thoroughly, however. We have made some changes in the updated Silverlight.js file which may impact your site's behavior.

  • Automatically Start Silverlight on Install - Part 2

    Silverlight 2 changes the default instantiation model of the Silverlight control from Silverlight.js to the <object> tag. This change makes it seem that Automatically Starting Silverlight on Install requires rewriting our instantiation code and moving back to the Silverlight.js model. Fortunately, you can get the same auto-restart behavior using the <object> model.

    My previous post on this subject called out that you need three things to build the auto-restart experience:

    1. A method for asking the browser if Silverlight is installed repeatedly, but without locking up the site.
    2. A way to tell that Silverlight is installed.
    3. An action to take once Silverlight is available.

    Only the second, a way to tell that Silverlight is installed, was provided by Silverlight.js. Everything else in that model is agnostic to the instantiation model. Since we can determine if Silverlight is installed using javascript without Silverlight.js we can rewrite the previous example to use the <object> instantiation method.

    Background

    These posts provide background information that will explain how/why this works:

    Implementation

    <html>

    <head>

        <title>Automatically Start Silverlight on Install</title>

        <script type="text/javascript">

            WaitForInstallCompletion = function()

            {

                try

                {

                    //This forces Firefox/Safari to refresh their

                    //list of known plugins.

                    navigator.plugins.refresh();

                }

                catch(e)

                {

                    //IE does not support the method, so an

                    //exception will be thrown.

                }

                if ( isSilverlightInstalled() )

                {

                    //Silverlight is installed. Refresh the page.

                    window.location.reload(false);

                }

                else

                {  

                    //Wait 3 seconds and try again

                    setTimeout(WaitForInstallCompletion, 3000);

                }   

            };

            onLoad = function()

            {

                //This only works if we are performing a clean install,

                //not an upgrade.

                if ( !isSilverlightInstalled() )

                {

                    //Silverlight is not installed. Try to refresh

                    //the page when it is installed.

                    WaitForInstallCompletion();

                }

            }

            function isSilverlightInstalled()

            {

                var isSilverlightInstalled = false;

               

                try

                {

                    //check on IE

                    try

                    {

                        var slControl = new ActiveXObject('AgControl.AgControl');

                        isSilverlightInstalled = true;

                    }

                    catch (e)

                    {

                        //either not installed or not IE. Check Firefox

                        if ( navigator.plugins["Silverlight Plug-In"] )

                        {

                            isSilverlightInstalled = true;

                        }

                    }

                }

                catch (e)

                {

                    //we don't want to leak exceptions. However, you may want

                    //to add exception tracking code here.

                }

                return isSilverlightInstalled;

            }

        </script>

    </head>

    <body onload="onLoad()">

      <div id='errorLocation' style="font-size: small;color: Gray;"></div>

     

      <div id="silverlightControlHost">

       

        <object data="data:application/x-silverlight," type="application/x-silverlight-2-b1" width="320" height="320">

          <param name="source" value="http://silverlight.net/samples/2b1/DynamicLanguageSDK/samples/clock-py/app.xap"/>

          <param name="background" value="#00000000" />

          <param name="windowless" value="true" />

         

          <a href="http://go.microsoft.com/fwlink/?LinkID=108182" style="text-decoration: none;">

              <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/>

          </a>

        </object>

        <iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>

      </div>

    </body>

    </html>

    Explanation

    As you can see, I replaced the call to Silverlight.isInstalled("1.0") with a call to isSilverlightInstalled(); Since we don't care about the version of Silverlight, this function is sufficient. Next, I replaced the call to CreateSilverlight() and thus Silveright.js with a Silverlight <object> element. And that's it. The rest of this example works just like the Silverlight.js implementation.

  • Determining if Silverlight is installed using Javascript

    In my recent post entitled Automatically Start Silverlight on Install I discussed a method for starting Silverlight once it is installed without any user interaction. The method discussed in that post relied on Silverlight.js, the helper file used for Silverlight 1.0 instantiation. Since Silverlight 2 predominantly uses <object> tags for instantiation, I want to show how to get the same behavior without the use of Silverlight.js. As a first step, I will talk about determining if Silverlight is installed without using Silverlight.js.

    As you probably guessed, the model for determining if Silverlight is installed differs between IE and Firefox/Safari. I will discuss the models separately and then provide a unified method that can answer the question "Is Silverlight installed?".

    Internet Explorer
    IE sees Silverlight as an ActiveX control and allows us to use standard ActiveX patterns to determine if the control is installed. Specifically, we will ask IE to create a Silverlight instance for us. This is accomplished by the following call:

    new ActiveXObject('AgControl.AgControl');

    If Silverlight is installed then this call will return an instance of a Silverlight control. Otherwise, the call will throw an exception which tells us that AgControl.AgControl is not defined. With this in mind, we can now write a method which will tell us if Silverlight is installed in IE:

    function isSilverlightInstalledIE()

    {

        var isSilverlightInstalled = false;

       

        try

        {

            var slControl = new ActiveXObject('AgControl.AgControl');

            //this line is only reached if Silverlight is installed

            isSilverlightInstalled = true;

        }

        catch (e)

        {

            //if Silverlight is not installed, an exception will be

            //thrown. We can ignore this exception in this method.

        }

        return isSilverlightInstalled;

    }

    Firefox and Safari
    Firefox and Safari see Silverlight as a plugin. Therefore, we can use the browser DOM's navigator.plugins array to determine if Silverlight is installed as so:

    function isSilverlightInstalledFFSafari()

    {

        var isSilverlightInstalled = false;

       

        try

        {

            if ( navigator.plugins["Silverlight Plug-In"] )

            {

                //this block is only reached if Silverlight is

                //installed

                isSilverlightInstalled = true;

            }

        }

        catch (e)

        {

            //if the browser does not support the plugins array

            //then an exception will be thrown. We can ignore

            //the exception in this method.

        }

        return isSilverlightInstalled;

    }

    Combined
    Finally, we can combine the above methods into a single isSilverlightInstalled() function:

    function isSilverlightInstalled()

    {

        var isSilverlightInstalled = false;

       

        try

        {

            //check on IE

            try

            {

                var slControl = new ActiveXObject('AgControl.AgControl');

                isSilverlightInstalled = true;

            }

            catch (e)

            {

                //either not installed or not IE. Check Firefox

                if ( navigator.plugins["Silverlight Plug-In"] )

                {

                    isSilverlightInstalled = true;

                }

            }

        }

        catch (e)

        {

            //we don't want to leak exceptions. However, you may want

            //to add exception tracking code here.

        }

        return isSilverlightInstalled;

    }

    Limitations
    The isSilverlightInstalled function does not tell us anything about the installed version. It only tells us if some version of Silverlight is installed.

     

    The combined isSilverlightInstalled function gives us the same information as Silverlight.isInstalled in the Auto Start sample. In my next post, I will merge isSilverlightInstalled, <object> instantiation, and the Auto Start sample to show how you can use the Auto Start method with Silverlight 2.

  • Automatically Start Silverlight on Install - Part 1

    The last step of the Silverlight installer is to ask the user to restart or refresh their browser. This approach forces the browser to re-evaluate the page's Silverlight instantiation logic once the control is installed. In the case of non-IE browsers, the restart also forces the browser to refresh its cache of known controls.

    While this experience is sufficient for most websites, it can be disruptive to sites which want to provide a managed end-to-end user experience. Fortunately, through the use of some simple javascript, these websites can detect when Silverlight installation completes and can launch their Silverlight content without any further user interaction.

    Prerequisites

     To get started, we need several logical components: 

    1. A method for asking the browser if Silverlight is installed repeatedly, but without locking up the site.
    2. A way to tell that Silverlight is installed.
    3. An action to take once Silverlight is available.

    For the first component we can use the commonly available setTimeout and setInterval methods. For the purposes of this post I will use setTimeout since it doesn't require us to explicitly cancel future executions. You should evaluate both methods and determine which works best for your scenario.

    The second component is also rather easy. The Silverlight.js helper file, available in the Silverlight SDK, provides a method named isInstalled which answers this very question.

    Finally, what action should the page take when it detects that Silverlight is installed? The simplest answer is to refresh itself. This will enable the default instantiation logic to render the Silverlight application without any additional modifications.

    Implementation

    <html>

    <head>

        <title>Automatically Start Silverlight on Install</title>   

        <script type="text/javascript">

            WaitForInstallCompletion = function()

            {

                try

                {

                    //This forces Firefox/Safari to refresh their

                    //list of known plugins.

                    navigator.plugins.refresh();

                }

                catch(e)

                {

                    //IE does not support the method, so an

                    //exception will be thrown.

                }

                if ( Silverlight.isInstalled("1.0") )

                {

                    //Silverlight is installed. Refresh the page.

                    window.location.reload(false);

                }

                else

                {  

                    //Wait 3 seconds and try again

                    setTimeout(WaitForInstallCompletion, 3000);

                }   

            };

            onLoad = function()

            {

                //This only works if we are performing a clean install,

                //not an upgrade.

                if ( !Silverlight.isInstalled("1.0") )

                {

                    //Silverlight is not installed. Try to refresh

                    //the page when it is installed.

                    WaitForInstallCompletion();

                }

            }

        </script>

    </head>

    <body onload="onLoad()">

        <!—-

    These references should be changed to point at the corresponding files in your web application

        -->

        <script type="text/javascript" src="Silverlight.js"></script>

        <script type="text/javascript" src="CreateSilverlight.js"></script>

        <div id="AgControl1Host">

            <script type="text/javascript">

                createSilverlight();

            </script>

        </div>

    </body>
    </
    html>

     

    Limitations
    This approach is limited to new installations of Silverlight. Websites which require a newer version of Silverlight than what is already installed on the user's machine will still require a restart. Fortunately, Silverlight's automatic updater makes new version requirements a transient problem.

    Conclusion
    The Silverlight installation process provides a good user experience with minimal requirements for the web author. The script solution presented in this post builds on the default experience by helping websites take more control their end-to-end flow.


© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker