Improve WPF application startup using ClickOnce On-Demand Download

In this blog (see item 11.) we discussed the fact that ClickOnce can have a significant effect on application start app time.

For standalone applications (both WPF and Winform apps) if you use the default settings in Visual Studio, ClickOnce will access the site-of-origin server (e.g. company network or internet) to check for a newer version before the application start. As expected, this will slow down the overall application startup. You can consider modifying this default setting to check for a new version after the application starts.

In the XBAP case this is not configurable. ClickOnce will always check the deployment site (site-of-origin) for updates before the XBAP starts.

In certain scenarios, you can consider using the ClickOnce Deployment APIs to download a smaller part of your application (for example, code required only for the first screen of the application) and download the rest of your app modules at a later stage, in the background, as they are needed. If your app is large, this could significantly improve your application startup performance the first time it runs.

It is also very possible that your end-user will not use certain portions of the application, so if you can identify what they are and avoid downloading them it could provide a big win.

Below I have a sample XBAP that shows how you can use the ClickOnce Deployment APIs to achieve this. Note that this approach works both for Standalone and XBAPs applications.

Although the overall size of my sample is 13MB in size, the application downloads and displays relatively quickly since at first we only download the main app module which is only 9KB in size.

The large image resources (~13MB) are contained in a separate module (SimpleOnDemandLibraray.dll) and are not downloaded at startup. SimpleOnDemandLibraray.dll is downloaded in the background from the XBAP site-of-origin only when user clicks on the button.

After launching XBAP this is what is shown:

OnDemand1 

Only when users click on the button the ~13MB module (SimpleOnDemandLibraray.dll) which contains the image resources downloads in the background.
Your app could display a fancier progress UX then mine…:)
OnDemand2
Sometime later, when download completes the image shows as below:OnDemand3

To enable this you need specifcy that SimpleOnDemandLibraray.dll is an optional component.
You can do this in Visual Studio in the Properties/Publish/ Application Files property page like here:

OnDemand4

The code is very simple and looks like this:

 private void InvokeDownloadGroup(object sender, RoutedEventArgs e)
 {
      try
      {
         Status.Visibility = Visibility.Visible;      
         ApplicationDeployment thisApp = ApplicationDeployment.CurrentDeployment;
         thisApp.DownloadFileGroupCompleted +=
                   new DownloadFileGroupCompletedEventHandler(DownloadFileGroupCompleted);
         thisApp.DownloadFileGroupAsync("OnDemandGroup1"); // Start the download
       }
       catch (Exception exp)
       {
         Status.Visibility = Visibility.Collapsed;
         onDemandResult.Content = "Failed: " + exp.Message.ToString();
       }
 }
  
 // Called when download completes
 void DownloadFileGroupCompleted(object sender, DownloadFileGroupCompletedEventArgs e)
 {
      Status.Visibility = Visibility.Collapsed;
      // Show an image from the downloaded group to demonstrate it is available from this 
      // event forward...
      Image myImage = new Image();
      BitmapImage myBitmapImage = new BitmapImage();
      myBitmapImage.BeginInit();
      myBitmapImage.UriSource = 
                 new Uri("pack://application:,,,/SimpleOnDemandLibrary;component/LargeImage.JPG");
      myBitmapImage.EndInit();
      myImage.Source = myBitmapImage;
      MyParent.Children.Add(myImage);
 }

Special thanks to Matt Galbraith who helped with this sample.

More info on the ClickOnce Deployment API is here: https://msdn.microsoft.com/en-us/library/ak58kz04(VS.80).aspx

To download XBAP sample (.zip) click here.