Sponsored Links


Resources

.NET Research Library
Get .NET related white papers, case studies and webcasts

Run From WebRun From WebRun From Web Discuss DiscussDiscuss Printer friendly Printer friendlyPrinter friendly
Run From Web

July 20, 2004

Download the accompanying source code


Introduction

Sometimes the best installer is none at all. What could be simpler than copying your executable to a web server and letting your users run the application directly from there? All you have to do to rollout a new version is to copy a new set of assemblies and supporting files to the virtual directory on the site. Users are automatically running the latest version. It sounds too good to be true.

Well, like everything that sounds too good to be true, there’s the “yeah, but” part. In this case, the “yeah, but” part is security. In this article, we’ll look at the restrictions imposed by the .NET security policy, and how you can work within them.

The ability to run a .NET executable residing on a web server is a technology developed in response to a number of limitations with other environments used for building web-based applications. Most notably, that web forms create a user experience that runs the gamut from painful to downright unworkable. As an example, I was posting a blog post a couple weeks ago. I made a simple typo, and hit the “backspace” button. Unfortunately, I bumped a mouse button and focus had moved off the edit control. The sad result: I lost a two page post. Similar problems occur in every web application everyday. Another advantage of Windows forms is that you have a richer palette of tools to develop windows forms applications than you have for web forms applications. Would you rather write applications in C# or VB.NET, or is EcmaScript your language of choice? In short, a browser was built for browsing. The lower cost of development and deployment has made web applications ubiquitous. These applications are exactly where you should look for opportunities to make use of zero deployment applications. You can improve the user experience by replacing the web interface with a downloadable smart client.

This form of zero-touch deployment works only for applications that are 100% managed code. The CLR can verify the safety of a managed application. If your application contains any unmanaged code, even raw memory access in C#, the CLR will not run your application.

As an example, I wrote a small windows forms application that interacts with a web service. It’s a simple app (see figure 1) that returns random quotes. You can also search for quotes. The application uses a web service to retrieve the quotes. It’s the kind of application you probably write everyday: make a request to a server, and display the results.

Using Windows Forms as the UI makes it very easy to implement a number of improvements that would be difficult in a web application using Web forms as an interface. As you can see, I’ve added tabs for the current session and previous session history. The second tab displays the history of all the quotes you’ve ever requested. This history, and in fact all information about this users client sessions, are kept at the client. There is no need to keep any user state at the server. This keeps your server code more cohesive. All in all, your application gives the user a richer experience, and your server code is simpler. Add that to the simpler deployment, and this is a technique you must have in your arsenal.

The simplest installer you’ll ever build.

Building the client application follows all the same techniques you’ve already employed for a web service client. Add your web reference, and build the code for the application. Once you’ve built the application, you need to place the executable in some virtual directory on your web server. That’s it. You’re done. Well, unless you expect any future updates. So, let’s discuss how to prepare for that eventuality. I personally like to create a separate server directory for the application, and for each version. I created that directory under the web service implementation for this article to make the download a little simpler. (See figure 2.) Once you’ve created the server directories and added the executable, it will make your users happy to have a web page to launch your application. See below:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <title>Random Quote Client Launcher</title>
    <meta name="GENERATOR"
      content="Microsoft Visual Studio .NET 7.1">
    <meta name="ProgId"
      content="VisualStudio.HTML">
    <meta name="Originator"
      content="Microsoft Visual Studio .NET 7.1">
  </head>
  <body>
    <P>This page contains the random quote client.</P>
    <P>Click <a href="ClientApplication/1.0.0.0/RandomQuoteClient.exe">
      here to run the sample.</P>
 </body>
</html>

This page won’t win any design awards, but it gets the job done. The <a> tag specifies a link that references the executable on the server. When the user clicks it, as long as he has the .NET Framework installed, the client application runs. (You can also install a shortcut on each users’ desktop to point to the final target:

http://<server>/ClientApplication/1.0.0.0/RandcomQuoteClient.exe) You can place any future updates in other directories on the server. By updating the link, you can change the version that your users get. If you want to go a step farther, you can map a virtual directory to the current version and change that mapping so that your users always get the current version.

Of trust and security

The Quote client runs because it is fully managed code, and the CLR can verify that it is reasonably well behaved. By reasonably well behaved, that means it does not have any buffer overruns, does not access raw memory, or use native libraries or COM objects that might do any of those nasty actions. But that doesn’t mean it’s completely safe. Managed code can create and delete files, modify the registry, access network resources, and do many other useful, but possibly dangerous, actions. So the CLR places numerous restrictions on downloaded executables to protect your computer. You get a restricted version of the file open dialog: you can’t save, create folders, or delete anything. You can only use “safe printing”, not the full printing mechanisms. You cannot use the Reflection.Emit classes. Your application is given restricted network access: it can only access the site from which it was downloaded. Finally, you can’t access the registry. Some of these restrictions are lifted when the downloaded assembly comes from a trusted intranet site. Applications that come from the same domain are not fully trusted, but have more trust than the big wild internet. I prefer to aim for the least privileges and try to allow an application to be run from anywhere on the web. This technique lets me raise security restrictions for my local intranet, and provides yet more safety for my users. Which brings me to Isolated Storage.

Isolated Storage is a mechanism whereby your assembly or application domain gets assigned a special directory for data storage. This isolation is a two way street: Your application can write in its own isolated storage location, regardless of where it was accessed. Also, no other application can access that directory and modify your files. Isolated storage is your application’s private space on the disk to store date. But, it is not hidden or encrypted. Do not use isolated storage as a means to store passwords or other sensitive information, unless you encrypt it with other means as well.

I added a permanent history feature to the random quotes sample to give you a flavor for using isolated storage. When the application exits, it writes all the current quotes to a file called “QuoteHistory.txt” in its isolated storage directory:

private void Form1_Closing(
  object sender, System.ComponentModel.CancelEventArgs e)
{
  // Save the current quotes to an isolated storage location:
  IsolatedStorageFile iso =
    IsolatedStorageFile.GetUserStoreForDomain( );

  IsolatedStorageFileStream historyStream =
    new IsolatedStorageFileStream
    ("QuoteHistory.txt", FileMode.Create, iso);

  StreamWriter wr = new StreamWriter( historyStream );
  foreach( string quote in this.textBoxHistory.Lines)
    wr.WriteLine(quote);
  foreach( string quote in this.textBoxCurrent.Lines)
    wr.WriteLine(quote);
  wr.Close();

}

This code should look very familiar, except for the first two statements. The IsolatedStorageFile.GetUserStoreForDomain() method returns an IsolatedStorageFile object that represents the Isolated Storage space for this application and this user. In Windows XP, this will map to some location under C:\Documents and Settings\<username>\Local Settings\Application Data\Isolated Storage. The IsolatedStorageStream constructor creates a file in that isolated storage space. After that, it’s just like any other file stream.

If you’re saving information to Isolated Storage, you should read that information back in.

private void Form1_Load(object sender, System.EventArgs e)
{

  // Save the current quotes to an isolated storage location:
  IsolatedStorageFile isoStore =
    IsolatedStorageFile.GetUserStoreForDomain( );

  string[] files = isoStore.GetFileNames("QuoteHistory.txt");
  if ( files.Length > 0 )
  {
    StreamReader reader = new StreamReader(
      new IsolatedStorageFileStream(
      "QuoteHistory.txt", FileMode.Open,isoStore));

    string quote = reader.ReadLine();
    while( quote != null )
    {
      textBoxHistory.Text += quote;
      textBoxHistory.Text += System.Environment.NewLine;
      quote = reader.ReadLine( );
    }
    reader.Close();
  }
}

Once again, the code should look mostly familiar to you. We’ll retrieve our own Isolated Storage folder and check for the existence of the history file. If the file is found, its contents are read, and added to the history pane.

There are system limitations on the size of the Isolated Storage, that are configured through the .NET Framework Configuration tool. The default size for the internet zone is 10240 Megabytes. That would let you download a lot of quotes. But, it should still prevent malicisous applications from flooding the users’s disk. Applications downloaded from intranet or other trusted sites, have larger allocations.

Look for opportunities

All in all, zero deployment is a step up from web forms. And, you can’t argue with the simplicity of the deployment model. Look for those applications where the download is small enough that your users are not waiting forever. (Microsoft Word would be a bad candidate for zero deployment). Also, consider how much access to protected system resources do you really need. A lot of the applications you write on a day to day basis really can be satisfied with minimal access to the local machine’s resources. When that’s the case, consider a Windows Forms application that can be accessed from a web page. The CLR uses CAS and verifiable code to ensure safety for your users, and you can give them greater functionality and simpler access to updates.

Figures

Authors

A commercial software developer and co-founder of SRT Solutions, Inc., Bill Wagner facilitates adoption of .NET in clients' product and enterprise development. His principal strengths include the core framework, the C# language, Smart Clients, and service oriented architecture and design. In 2003 Microsoft recognized his .NET expertise appointing him Regional Director for Michigan. A frequent writer and speaker, Bill's work is published in ASP.NET Pro and Visual Studio Magazine. He is the author of C# Core Language Little Black Book and Effective C#.

News | Blogs | Discussions | Tech talks | White Papers | Downloads | Articles | Media kit | About
All Content Copyright ©2007 TheServerSide Privacy Policy
Site Map