Dennis van der Stelt

The most votes generally drown out the best votes

Community

News

  • Meet me at PDC08

Email Notifications

I read...

I Use...

Tags

Recent Posts

Archives

November 2007 - Posts

Silverlight 2.0

You probably all read Scott Guthries weblog, so I don't even have to create a link to it! ;-)

But he just announced Silverlight 2.0. It's basically 1.1 with too many features to call it a point release. And while the list below isn't the final list, it's a cool list to see what's coming in 2.0. A beta with GoLive license will be released Q1 2008. Hopefully sooner than later. And instead of just playing around with it, I'll try to write some blog entries for it. One of my wishes is to build the Class-A WinterClass banner in Silverlight with snow that'll stick on the ground or even on the Class-A logo or so.

Here's Scott's list of new features in Silverlight 2.0

  • WPF UI Framework: The current Silverlight Alpha release only includes basic controls support and a managed API for UI drawing.  The next public Silverlight preview will add support for the higher level features of the WPF UI framework.  These include: the extensible control framework model, layout manager support, two-way data-binding support, and control template and skinning support.  The WPF UI Framework features in Silverlight will be a compatible subset of the WPF UI Framework features in last week's .NET Framework 3.5 release.

  • Rich Controls: Silverlight will deliver a rich set of controls that make building Rich Internet Applications much easier.  The next Silverlight preview release will add support for core form controls (textbox, checkbox, radiobutton, etc), built-in layout management controls (StackPanel, Grid, etc), common functionality controls (TabControl, Slider, ScrollViewer, ProgressBar, etc) and data manipulation controls (DataGrid, etc).

  • Rich Networking Support: Silverlight will deliver rich networking support.  The next Silverlight preview release will add support for REST, POX, RSS, and WS* communication.  It will also add support for cross domain network access (so that Silverlight clients can access resources and data from any trusted source on the web).

  • Rich Base Class Library Support: Silverlight will include a rich .NET base class library of functionality (collections, IO, generics, threading, globalization, XML, local storage, etc).  The next Silverlight preview release will also add built-in support for LINQ to XML and richer HTML DOM API integration.

Technorati Tags:
Turn off automatic updates with ClickOnce

I got an e-mail with the question how to turn off automatic checking for updates, when you're doing a manual check for updates with ClickOnce. Strangely enough I forgot to mention this in my previous article.

ClickOnceAutoUpdateOff

The above dialog window can be obtained in the properties window of your project (Right-click your project in the solution explorer), under the "Publish" tabpage, using the "Updates..." button.

In the above window the "The application should check for updates" is turned on. Uncheck it and your application won't automatically check for updates anymore.

Note that at the bottom, I've filled in the update location. For some reason, when you deploy your application with auto update turned off, it won't be able to find the update location anymore. It's being removed from the manifest! I have no idea if this is a bug or not, but it can be solved by entering the update location in the bottom textbox. Now the manual check for updates with ClickOnce works again.

Technorati Tags:
Borrow and extend; Summer Class

When Microsoft takes a great idea from someone else, they always enhance it. They call this "borrow and extend". Take tabbed browsing for example, where you can view QuickTabs and get a screen with every open tab in a preview window.

It seems other companies also try this, copying our Summer Class (2006 & 2007) and Winter Class idea, but it seems they don't get Microsoft's "borrow and extend" very well.

Our Winter Classes are at least six times better

  1. Microsoft related instead of 'that other technology/language'
  2. Everything there is to know about .NET 3.5 or Business Intelligence
  3. A complete week offline in a great hotel, 100 meters from the beach, everything arranged
  4. The best trainers in The Netherlands
  5. Gameplay during the evening. When you register, we're open for discussion about the game(s) :-)
  6. The ability to build real world applications, because you heard everything; not just the marketing tale

So register before it's too late. Places are limited!

~Visual Studio 2005

Forget about VPC, VMWare and the likes, I finally got it on my laptop!

vs2008about

Let's play...

Oh, by the way, after I've finished Call of Duty 4. This game ROCKS!

.NET Framework 3.5 in February

Normally I get flooded with messages about stuff like the official release-date for .NET Framework 3.5. But since my Omea Reader database crashed (for the third time, but this time I can't find a solution to get it working again) and I still haven't added a lot of blogs again, the only resource I've come across that said it was Daniel Moth's weblog.

Anyway, Daniel Moth just said .NET Framework 3.5 and Visual Studio 2008 will be officially released in February next year, but we should be able to get a hold on both before the end of this year. I've been wondering about this, since November has been the month for Microsoft to release this kind of stuff. But since the RC1 hasn't been (publicly) released yet, I was wondering if they'd skip it. I still am, but they're probably going to release RTM right after Beta 2.

He's got a list of 10 things you should know about Visual Studio 2008 and .NET Framework 3.5. There's quite good stuff in there with links to more resources. I like that about The Moth, especially because links are often to his own weblog, sharing valuable information.

The only thing I don't completely agree upon is point 3. My mobile application was build using multi-targeting in VS2008 but the setup was created in Visual Studio 2005. You can't create setup projects that are based on the .NET Framework 2.0! :-)

Manual check for updates with ClickOnce

I really love [wikipedia:ClickOnce], because it removes the necessity to build a web application. In my years as a developer, I can't count the projects that were web based, simply because of the deployment model. And then ClickOnce came around. Now I can't count the times that I've explained during a training what ClickOnce is and why everyone should love it!

clickonce_autoupdate

Most people use the default behavior of ClickOnce, which presents a dialog window, checking for updates, as shown in the dialog above. I discourage people to use this default behavior because of two reasons. The first reason is that it's plain ugly and annoying. The second reason is that when an update is available but people skip the update process, they're not asked again for installation of the update, until a new version is deployed. We can solve this by manually checking for updates and this is even more interesting when doing it asynchronously.

Here's the simplest code for checking for an update. Be sure to include a reference to System.Deployment and a using to System.Deployment.Application.

ApplicationDeployment updateCheck = ApplicationDeployment.CurrentDeployment;

UpdateCheckInfo info = updateCheck.CheckForDetailedUpdate();

//

if (info.UpdateAvailable)

{

  updateCheck.Update();

  MessageBox.Show("The application has been upgraded, and will now restart.");

  Application.Restart();

}

Here you can see we gather information. There's also a property IsUpdateRequired which you can use to force users to upgrade (which is happening in this example, normally you'd give users a choice to update). In the default ClickOnce behavior, this results in automatic update, instead of being asked to update the application.

Of course we can add error checking and a BackgroundWorker to make things a little more pretty. We'll start out with the BackgroundWorker, bind the events for when it should perform work and for when it's completed and then start it up.
Note : In this example, we'll be adding everything in the main form, but it's better to apply the [wikipedia:Single_responsibility_principle] and delegate this to some helper classes.

BackgroundWorker bgWorker = new BackgroundWorker();

bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);

bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorder_RunWorkerCompleted);

bgWorker.RunWorkerAsync();

 

Now we'll have to add the code to peform the check. It's partially the code from code-sample #1, without the updating part.

private enum UpdateStatuses

{

  NoUpdateAvailable,

  UpdateAvailable,

  UpdateRequired,

  NotDeployedViaClickOnce,

  DeploymentDownloadException,

  InvalidDeploymentException,

  InvalidOperationException

}

 

/// <summary>

/// Will be executed when works needs to be done

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

void bgWorker_DoWork(object sender, DoWorkEventArgs e)

{

  UpdateCheckInfo info = null;

 

  // Check if the application was deployed via ClickOnce.

  if (!ApplicationDeployment.IsNetworkDeployed)

  {

    e.Result = UpdateStatuses.NotDeployedViaClickOnce;

    return;

  }

 

  ApplicationDeployment updateCheck = ApplicationDeployment.CurrentDeployment;

 

  try

  {

    info = updateCheck.CheckForDetailedUpdate();

  }

  catch (DeploymentDownloadException dde)

  {

    e.Result = UpdateStatuses.DeploymentDownloadException;

    return;

  }

  catch (InvalidDeploymentException ide)

  {

    e.Result = UpdateStatuses.InvalidDeploymentException;

    return;

  }

  catch (InvalidOperationException ioe)

  {

    e.Result = UpdateStatuses.InvalidOperationException;

    return;

  }

 

  if (info.UpdateAvailable)

    if (info.IsUpdateRequired)

      e.Result = UpdateStatuses.UpdateRequired;

    else

      e.Result = UpdateStatuses.UpdateAvailable;

  else

    e.Result = UpdateStatuses.NoUpdateAvailable;

}

The first thing you'll notice is that I've added an enumeration. This is for passing a result back to the method that's called when we're done.
Note : This can be done more gracefully, but it'll do for now without a lot of extra code. And it's not even real ugly! ;-)

In the bgWorker_DoWork method we first check if the application is deployed via ClickOnce. Then we gather the detailed information about a possible update and perform some error handling if things don't go the way we expect. Finally we check if an update is available and wether or not it's a required update. We pass this information into the result and end this method.

Now we're in need of the method when the work is done...

/// <summary>

/// Will be executed once it's complete...

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

void bgWorder_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

{

  switch ((UpdateStatuses)e.Result)

  {

    case UpdateStatuses.NoUpdateAvailable:

      // No update available, do nothing

      MessageBox.Show("There's no update, thanks...");

      break;

    case UpdateStatuses.UpdateAvailable:

      DialogResult dialogResult = MessageBox.Show("An update is available. Would you like to update the application now?", "Update available", MessageBoxButtons.OKCancel);

      if (dialogResult == DialogResult.OK)

        UpdateApplication();

      break;

    case UpdateStatuses.UpdateRequired:

      MessageBox.Show("A required update is available, which will be installed now", "Update available", MessageBoxButtons.OK);

      UpdateApplication();

      break;

    case UpdateStatuses.NotDeployedViaClickOnce:

      MessageBox.Show("Is this deployed via ClickOnce?");

      break;

    case UpdateStatuses.DeploymentDownloadException:

      MessageBox.Show("Whoops, couldn't retrieve info on this app...");

      break;

    case UpdateStatuses.InvalidDeploymentException:

      MessageBox.Show("Cannot check for a new version. ClickOnce deployment is corrupt!");

      break;

    case UpdateStatuses.InvalidOperationException:

      MessageBox.Show("This application cannot be updated. It is likely not a ClickOnce application.");

      break;

    default:

      MessageBox.Show("Huh?");

      break;

  }

}

Here you'll see responses to most error messages and them just showing up in a message box. Interesting is the NotDeployedViaClickOnce status, as this pops up every time you're debugging your application from Visual Studio. You might want to remove that message box. You also might want to remove the messagebox for when no update is available, as users aren't really interested in that. The final default switch should never occur.

Interesting are the switches for when there is an update, and when it's required. In the first case the user can ignore the update which he can't in the case it's required. You might think of something so the user won't be asked dozens of times every time the application is started.

Now we only need the UpdateApplication method.

private void UpdateApplication()

{

  try

  {

    ApplicationDeployment updateCheck = ApplicationDeployment.CurrentDeployment;

    updateCheck.Update();

    MessageBox.Show("The application has been upgraded, and will now restart.");

    Application.Restart();

  }

  catch (DeploymentDownloadException dde)

  {

    MessageBox.Show("Cannot install the latest version of the application. \n\nPlease check your network connection, or try again later. Error: " + dde);

    return;

  }

}

Here we again do some error checking for when things go wrong. But all we're doing here is update the application and restart it.

This is now all happening in the background without the users being notified when there's no update and without the annoying popup dialog. It's also really easy to create your own "Check for updates" button or menu option now.

Have fun with ClickOnce and forget about those awful web based applications! ;-)

UPDATE : Here's how you can turn off automatic updates with ClickOnce.

UPDATE 2 : Here's an example solution, without the BackgroundWorker.

Technorati Tags: