(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Building a Web Setup that configures your Silverlight application

(5 votes)
Jonathan van de Veen
>
Jonathan van de Veen
Joined Aug 27, 2009
Articles:   4
Comments:   12
More Articles
18 comments   /   posted on Apr 26, 2010

This article is compatible with the latest version of Silverlight.


Introduction

The most common scenario for a Silverlight application is to deploy it to the web. However, when building an application that is going to be used by companies, who need to deploy it to their own servers, a decent Setup is a must have. This article will take you through the steps of building a Web Setup to deploy your Silverlight application and allow you to configure it from the Web Setup.

You can download the full project here.

Step 1: Setting up the Web Setup project

As a starting point I’ve used a simple Silverlight application which has a connection to a very basic WCF service. This way we can test if everything works as expected (which will be the homework assignment :-) ). I’ve chosen to let Visual Studio create a Web Application for me, which we will use in the setup project. To avoid the whole cross-domain issue, I’ve published the service to my local IIS server, which is already setup for allowing cross-domain requests.

The first thing to do is to add a Web Setup project. You can do this by right-clicking your solution and clicking Add > New Project…. In the Project types tree, you select Other Project Types and then Setup and Deployment. You can then select Web Setup Project. Simply give it a name and hit OK.

CreateWebSetupProject

As a default you end up with an empty setup. It’s time to add some content to it. After you’ve created the project, you’re now presented with the File System window for the setup. There are four windows like this, all covering different parts of installing your solution. In the File System window, you can see the Web Application Folder. This is the folder that will hold your Silverlight Application. To add the Silverlight project to the Web Application Folder, you simply right-click it and choose Add > Project Output…. You can then choose for which project you want to add output and what type of output you want to add. In this case we want to select the Web project that was created by Visual Studio and we want it’s content.

AddProjectOutput

If you don’t have anything to configure for your Silverlight Application, this is it. You can tweak some settings in the Web Setup Project in order to make it fit your needs better, but technically you’re done. If you need to configure, let’s say, a Service Reference, please read on.

Just one more tip when using Setup projects. These projects are not built automatically when building the solution. In order to get the Setup to build with new code, you need to explicitly build the Setup project.

Step 2: Adding a custom action to configure your service references

To actually extend the setup to handle configuration for you, you need to have somewhere to put your code. Within the setup this can be done with an Installer Class. I’ve added a standard Class Library to the solution to hold the Installer Class and then I added an Installer Class.

AddInstallerClass

Now whenever a setup wants to execute an Installer it will call the Install method. So the logical next step for us is to override this method. Then we want to prepare some things for debugging. The first thing is to get the setup project to call the Installer. To do this we need to select the setup project in the solution explorer and then click the Custom Actions Editor button.

CustomActionsEditorButton

We then are presented with a simple tree that contains the various stages a setup can have. In this case we want our Installer to run in the Install stage of the setup, so we right click the Install folder and click Add Custom Action. In the dialog that follows we navigate into the Web Application Folder and then we click the Add Output button. Like before we can then add the output of some project in our solution. In this case we want the primary output from the Class Library project that contains our Installer. The setup will now execute our Installer.

Step 2.1: Writing code for our custom action

Another thing I do when building an Installer is to add some code for debugging. The reason for this is that you can’t just hit F5 and debug. Attaching to a setup is not so easy, so I tend to just have the Installer attach to a debugger:

 #if DEBUG
             Debugger.Launch();
 #endif

Now we want to do a couple of things inside the Install method:

  1. Open up our .xap file to get to our config file
  2. Read the config file so we know what to configure
  3. Change the configuration and write it back into the config file
  4. Put the config file back into the .xap file

Obviously we need some way to open up our .xap file. As this is technically a .zip file we need some library to deal with this for us. I’ve done some research on this and choose DotNetZip. Licensing was one of the reasons, but also the capability of simply replacing a files content right back into the .zip archive, instead of heaving to unzip to some folder and repackage the whole thing. Combined with the fact that this is a relatively small library and doesn’t require things like the J# libraries and that his appears to be a stable and well maintained open source project got me across.

In order to open the .xap file, first we need to find out where it is. In order to do that, we can use the currently executing Assembly to find the path. Here is what I wrote:

 Assembly executingAssembly = Assembly.GetExecutingAssembly();
 string location = executingAssembly.Location;
   
 DirectoryInfo clientRootDirectory = Directory.GetParent(location);
 string clientBinPath = Path.Combine(clientRootDirectory.Parent.FullName, "ClientBin");
 string xapFilePath = Path.Combine(clientBinPath, "SilverlightInstallerTest.xap");

The next step is to actually open the .xap file using the ZipFile class in the DotNetZip library and retrieve our config file. To get to the actual decompressed contents of the config file, we need to go through the ZipEntry instance that holds the config file:

 ZipFile zipFile = new ZipFile(xapFilePath);
 ZipEntry zipEntry = zipFile.Entries.First(e => e.FileName.Equals("ServiceReferences.ClientConfig"));
  
 Stream configStream = new MemoryStream();
 zipEntry.Extract(configStream);
 configStream.Seek(0, SeekOrigin.Begin);
 StreamReader configReader = new StreamReader(configStream);
   
 string config = configReader.ReadToEnd();

Notice that on line 6 we reset the configStream to go back to the beginning, so that we can be sure to start reading from the start after loading the stream from the .xap file.

Now that we have the contents of the config file we can load it into an XDocument instance so we can use Linq To XML to find the right element and the right attribute to change the configuration:

 StringReader reader = new StringReader(config);
 XmlReaderSettings xmlSettings = new XmlReaderSettings();
   
 XmlReader xmlReader = XmlReader.Create(reader, xmlSettings);
 XDocument configDocument = XDocument.Load(xmlReader);
 XName clientName = "client";
 var client = from element in configDocument.Elements().Elements().Elements()
              where element.Name.Equals(clientName)
              select element;

Obviously we want to use a parameter to configure the right service URL, so we can then have the user input the URL through the setups UI. I have not included the steps to add such a UI to the setup as this is well documented and beyond the scope of this artice. To get to a parameter called serviceurl, we write the following:

 string serviceUrl = Context.Parameters["serviceurl"];
 if (string.IsNullOrEmpty(serviceUrl))
 {
     throw new ArgumentNullException("serviceurl", "You must supply a service url");
 }

If no input was given by the user running the setup we want to throw an exception. This will abort the setup process. You can put in more advanced error checking if needed, for example to check for a valid URL format.

And finally all we need to do is write the new XML into the existing ZipEntry and save the ZipFile back to the file system:

 if (!client.Any())
 {
     return;
 }
 var securityEndPoint = from element in client.First().Elements()
                        where element.Attribute("name").Value.Equals("BasicHttpBinding_IService1")
                        select element;
 if (securityEndPoint.Any())
 {
     XElement element = securityEndPoint.First();
     XAttribute attribute = element.Attribute("address");
     attribute.SetValue(serviceUrl);
 }
   
 zipFile.UpdateEntry("ServiceReferences.ClientConfig", configDocument.ToString());
 zipFile.Save();

Notice the zipFile.Save() at the end. This will actually update the .xap file so that it now contains the correct configuration.

Conclusion

We have seen that it’s easy to create a web setup project that will install a Silverlight application in IIS if there is no configuration involved. Once the configuration becomes an issue you’ll need a custom action to do that configuration. Unzipping the configuration and replacing the configuration in the .xap file is easy with the DotNetZip library.


Subscribe

Comments

  • -_-

    RE: Building a Web Setup that configures your Silverlight application


    posted by SICKANDAR on May 09, 2010 00:54
    WHEN I DOWNLOADED AND TRY TO RUN,IT SEEMS THE ICONIC.ZIP IS MISSING
  • mrjvdveen

    RE: Building a Web Setup that configures your Silverlight application


    posted by mrjvdveen on May 10, 2010 09:52

    Hi, Sickandar,

    Sorry about that. I've uploaded a new version with the zip library in place in the debug folder, so you can run directly.

    I would like to encourage you to download the library from codeplex as well as this includes the licensing and documentation.

    Thanks for the heads up,

    Jonathan van de Veen

  • -_-

    RE: Building a Web Setup that configures your Silverlight application


    posted by Raise on May 22, 2010 16:26
    Thanks for posting. We will try this when we get to the installation part of our projects.
  • -_-

    RE: Building a Web Setup that configures your Silverlight application


    posted by Anonymous on Jun 12, 2010 10:22
    The source code download link is incorrect. I am unable to download the project. Please post the correct download link.
  • mrjvdveen

    RE: Building a Web Setup that configures your Silverlight application


    posted by mrjvdveen on Jun 14, 2010 09:07
    @Anonymous: I've tested it here and it works fine. Could you try again and tell me what is going wrong? Are you getting an error of some kind?
  • -_-

    RE: Building a Web Setup that configures your Silverlight application


    posted by aad on Jul 20, 2010 15:20

    Hello,

    I have created sample silverlight app with wcf service. I have done all the things as above. But I am facing prob of "Installer was interripted before Application could be installed. You need to restart the installer to try again."

    Please Reply.

  • mrjvdveen

    RE: Building a Web Setup that configures your Silverlight application


    posted by mrjvdveen on Jul 21, 2010 09:34

    @aad: This is usually caused by an exception that was thrown during the execution of the CustomAction. Attach a debugger, so you can find out where things go wrong. You can do so by following my tip in the start of step 2.1.

    HTH.

  • -_-

    RE: Building a Web Setup that configures your Silverlight application


    posted by A from London on Sep 29, 2010 12:11
    Very good post. Thanks
  • SwathiReddy

    Re: Building a Web Setup that configures your Silverlight application


    posted by SwathiReddy on Nov 17, 2011 08:07


    Thanks For the post.

    You have given an option of downloading the full project. I have downloaded and when i am installing the setup file, an error is coming while installing..........

    Exception Details:

    error 1001: exception occurred System.BadImageFormatException: Could not load file or assembly  'File"http://c:\inetpub\........\silverlightInstallerTest.setup.dll or one of its dependencies.

    I am new this silverlight..........Pls help me..........



  • mrjvdveen

    Re: Building a Web Setup that configures your Silverlight application


    posted by mrjvdveen on Nov 17, 2011 09:35

    @Swathi: I've downloaded the project myself and after building the entire solution and the setup project I ran into this error. It is caused by a faulty dependency setting for the .NET framework dependency in the setup project.

    To correct it:

    1. Open the solution explorer and find the setup project (SilverlightInstallerSetup).
    2. Open the Detected Dependencies folder and double click on Microsoft .NET Framework. This will open the Launch Conditions window.
    3. Find the .NET Framework dependencies in that window, right click it and click Properties Window.
    4. In the Properties Window change the Version property to .NET Framework 4.
    5. Rebuild the setup project and try again.

    It should now try to launch a debugger while installing. This is normal behavior. Simply choose to attach it to the VS you already have open and if you don't want to debug, just hit F5 to continue.

    HTH.

    Jonathan

  • SwathiReddy

    Re: Building a Web Setup that configures your Silverlight application


    posted by SwathiReddy on Nov 17, 2011 12:42

    @Jonathan:

    Thank You

  • sagarT

    Re: Building a Web Setup that configures your Silverlight application


    posted by sagarT on Dec 26, 2011 11:33

         I have created demo project but it will throw Access to the path 'C:\Demo\New Folder\ClientBin\SilverlightApplication.xap' is denied. error.

         What is the solution for above problem?

  • mrjvdveen

    Re: Building a Web Setup that configures your Silverlight application


    posted by mrjvdveen on Dec 26, 2011 11:43
    @sagarT: I'm not sure I understand what you mean. When does this exception occur exactly? Is it when you build or when you run the setup or when you run the application?
  • sagarT

    Re: Building a Web Setup that configures your Silverlight application


    posted by sagarT on Dec 26, 2011 11:58
    In my project I have created one function to update .xap file.Error is coming when zipFile.Save() method is called.
  • sagarT

    Re: Building a Web Setup that configures your Silverlight application


    posted by sagarT on Dec 26, 2011 12:44
    In my project I have created one function to update .xap file.Error is coming when zipFile.Save() method is called.
  • mrjvdveen

    Re: Building a Web Setup that configures your Silverlight application


    posted by mrjvdveen on Dec 26, 2011 15:08
    Sounds to me like you either not have access to the .xap file (either it's read-only, in use or the user executing the code doesn't have access to the .xap file) or the file is not in the specified location. I'd put a breakpoint before zipFile.Save is called and then go into windows explorer to find out if the file is there and if so if it's read only for some reason. If not, try to edit it manually, both with the debugger still on break and after termination. That should give you enough information to figure it out.
  • sofaki_10

    Re: Building a Web Setup that configures your Silverlight application


    posted by sofaki_10 on Feb 01, 2012 17:54

    Hello,

    This post is really solving my problem, but I cannot seem to run it. I get the same error mensioned above "Installer was interripted before Application could be installed. You need to restart the installer to try again" but cannot find why am I getting it. I recreated the same setup project by your instructions and still getting the same mistake. Does anyone knows what is wrong and why am I getting this?? I really need this solution so any answer would be really appreciated.

    Thank you in advance

  • sofaki_10

    Re: Building a Web Setup that configures your Silverlight application


    posted by sofaki_10 on Feb 01, 2012 18:01

    Hello,

    This post is really solving my problem, but I cannot seem to run it. I get the same error mensioned above "Installer was interripted before Application could be installed. You need to restart the installer to try again" but cannot find why am I getting it. I recreated the same setup project by your instructions and still getting the same mistake. Does anyone knows what is wrong and why am I getting this?? I really need this solution so any answer would be really appreciated.

    Thank you in advance

Add Comment

Login to comment:
  *      *