Example of ClickOnce Deployment

20 May 2012 by

Without any tool, deployment of desktop application is really painful. In the old day, developers need to write an auto-updated application by themselves. However, now ClickOnce, Microsoft product, could leverage this task easily. ClickOnce allows user to setup and run program directly from a webpage. The deployment files will be published to the a friendly URL and then access at the client computer. There is an option for client to check update every program run or any point in the program. This technique is very similar to Java Web Start.

I will show how to achieve it in this demo.

 1. Architecture

ClickOnce Architecture

2. Source Code

I just want to show a snapshot of code in LoginForm and UpdateForm.

LoginForm

using System;
using System.Deployment.Application;
using System.Windows.Forms;

namespace RVD.Win.View
{
  public partial class LoginForm : Form
  {
    public LoginForm()
    {
      InitializeComponent();
    }

    private void LoginForm_Load(object sender, EventArgs e)
    {
      CheckForUpdate();
    }

    private void CheckForUpdate()
    {
      var appDeploy = ApplicationDeployment.CurrentDeployment;

      //Check for update
      var update = appDeploy.CheckForDetailedUpdate();
      if(appDeploy.CheckForUpdate())
      {
        MessageBox.Show(@"The system needs to be updated to version: " + update.AvailableVersion, @"Update",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
        var deployForm = new AppDeployPopup {AppDeploy = appDeploy, IsUpdateAvailable = true};
        deployForm.ShowDialog();

        if (deployForm.ShouldAppRestart)
        {
          Visible = false;
          Close();  
          Application.Restart(); 
        }
      }
    }
  }
}

UpdateForm here, I would call AppDeployPopup. We are invoking
UpdateAsync()
method to update the software asynchronously. This method support two events called AsyncCompletedEvent and DeploymentProgressChangedEvent. We will use this event to show downloading progress in the form as well as closing the form after updating is completed.

using System;
using System.ComponentModel;
using System.Deployment.Application;
using System.Windows.Forms;

namespace RVD.Win.View.Popup
{
  public partial class AppDeployPopup : Form
  {
    public AppDeployPopup()
    {
      InitializeComponent();
    }

    #region Properties

    public ApplicationDeployment AppDeploy { get; set; }

    public bool IsUpdateAvailable { get; set; }

    public bool ShouldAppRestart { get; set; }

    #endregion

    private void AppDeployPopup_Load(object sender, EventArgs e)
    {
      Cursor = Cursors.WaitCursor;

      try
      {
        if (IsUpdateAvailable) BeginUpdate();
      }catch(Exception exception)
      {
        MessageBox.Show(@"Unexpected error during updating this software. \n" + exception.Message);
      }finally
      {
        Cursor = Cursors.Default;
      }
    }

    private void BeginUpdate()
    {

      AppDeploy.UpdateCompleted += new AsyncCompletedEventHandler(AppDeploy_UpdateCompleted);

      AppDeploy.UpdateProgressChanged += new DeploymentProgressChangedEventHandler(AppDeploy_UpdateProgressChanged);

      AppDeploy.UpdateAsync();
    }

    private void AppDeploy_UpdateCompleted(object sender, AsyncCompletedEventArgs e)
    {
      ShouldAppRestart = false;
      if (e.Cancelled)
      {
        MessageBox.Show(@"The update of the application's latest version was cancelled.", @"Warning",
                        MessageBoxButtons.OK, MessageBoxIcon.Warning);
      }
      else if (e.Error != null)
      {
        MessageBox.Show(@"There was an error during updating. Please contact your system administrator.", @"Error",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
      }
      else
      {
        ShouldAppRestart = true;
      }
      Close();
    }

    private void AppDeploy_UpdateProgressChanged(object sender, DeploymentProgressChangedEventArgs e)
    {
      var progressText = String.Format("Downloading: {0:D}K out of {1:D}K downloaded - {2:D}% complete", e.BytesCompleted/1024,
                                          e.BytesTotal/1024, e.ProgressPercentage);
      lblDownloadStatus.Text = progressText;
      pgbDownload.Value = e.ProgressPercentage;
    }
  }
}

Continue Reading »

No responses yet