AutomaticUpdater tutorial for Windows Services and Console Apps

This article will teach you how to use the AutomaticUpdater in apps without a UI such as Windows Services and console apps. If you're making an app with a graphical user interface, then see one of the following articles:

If you're making a GUI app that happens to have Windows Services that you'd like to update, then you can just use the GUI version of the AutomaticUpdater and Start and Stop Windows Services as part of your update.

First, get wyBuild

You need wyBuild to use the AutomaticUpdater, so download wyBuild now. You can use it free for 21-days with no restrictions. And if you don't like it you can uninstall it - no hard feelings & no files laying around.

Then, work yourself through steps 1-3 of the step-by-step walkthrough. This will teach you how to make update patches. Once you've read the walkthrough you're ready to add the AutomaticUpdater to your app:

Step 1: Add "AutomaticUpdater.dll" reference to your app

The first thing you need to do is add the AutomaticUpdater.dll reference to your app. You can do this by right clicking the "References" folder in Visual Studio, clicking "Add Reference...", then choosing the "Browse" tab in the "Add references" dialog:

Adding AutomaticUpdater reference to your project

Then simply choose the correct AutomaticUpdater.dll for your app. There are 2 separate builds of the AutomaticUpdater: one for .NET 2.0, 3.0, and 3.5 apps and one for .NET 4.x apps.

For .NET 2.0, 3.0, and 3.5 apps

If your app is compiled for .NET 2.0, 3.0, or 3.5 then use AutomaticUpdater.dll located in the "AutomaticUpdater" folder:

C:\Program Files\wyBuild\AutomaticUpdater\AutomaticUpdater.dll
	or
C:\Program Files (x86)\wyBuild\AutomaticUpdater\AutomaticUpdater.dll

For .NET 4.x apps

If your app is compiled for .NET 4.x then use AutomaticUpdater.dll located in the "AutomaticUpdater\Microsoft .NET 4.0" folder:

C:\Program Files\wyBuild\AutomaticUpdater\Microsoft .NET 4.0\AutomaticUpdater.dll
	or
C:\Program Files (x86)\wyBuild\AutomaticUpdater\Microsoft .NET 4.0\AutomaticUpdater.dll

Step 2: Using the AutomaticUpdaterBackend class

The AutomaticUpdaterBackend class contains all the functionality to add automatic updating to your service or console app. The way to use the AutomaticUpdaterBackend differs between Windows Services and Console Apps, so we've split it into 2 separate examples:

For Windows Services

If you're using the AutomaticUpdater with a Windows Service, the first thing you need to do is make sure your service will be installed as a "LocalSystem" service. Please note that a "LocalSystem" service is different than a "LocalService" service:

Create and instance of the AutomaticUpdaterBackend class in the OnStart() method of your service:

using wyDay.Controls;

static AutomaticUpdaterBackend auBackend;

protected override void OnStart(string[] args)
{
    auBackend = new AutomaticUpdaterBackend
                    {
                        //TODO: set a unique string.
                        // For instance, "appname-companyname"
                        GUID = "a-string-that-uniquely-IDs-your-service",

                        // With UpdateType set to Automatic, you're still in
                        // charge of checking for updates, but the
                        // AutomaticUpdaterBackend continues with the
                        // downloading and extracting automatically.
                        UpdateType = UpdateType.Automatic,

                        // We set the service name that will be used by wyUpdate
                        // to restart this service on update success or failure.
                        ServiceName = this.ServiceName
                    };

    auBackend.ReadyToBeInstalled += auBackend_ReadyToBeInstalled;
    auBackend.UpdateSuccessful += auBackend_UpdateSuccessful;

    //TODO: use the failed events for logging & error reporting:
    // CheckingFailed, DownloadingFailed, ExtractingFailed, UpdateFailed

    // Initialize() and AppLoaded() must be called after events have been set.
    // Note: If there's a pending update to be installed, wyUpdate will be
    //       started, then it will talk back and say "ready to install,
    //       you can close now" at which point your app will be closed.
    auBackend.Initialize();
    auBackend.AppLoaded();

    if (!auBackend.ClosingForInstall)
    {
        // sees if you checked in the last 10 days, if not it rechecks
        CheckEvery10Days();

        //Note: Also, since this will be a service you should call
        //      CheckEvery10Days() from an another thread (rather
        //      than just at startup)

        //TODO: do your normal service work
    }
}

You'll notice we made a call to a function CheckEvery10Days(). This function checks whether we checked in the last 10 days, and if not, begins checking for updates:

static void CheckEvery10Days()
{
    // Only ForceCheckForUpdate() every N days!
    // You don't want to recheck for updates on every app start.

    if ((DateTime.Now - auBackend.LastCheckDate).TotalDays > 10
        && auBackend.UpdateStepOn == UpdateStepOn.Nothing)
    {
        auBackend.ForceCheckForUpdate();
    }
}

Since we set the UpdateType to UpdateType.Automatic, when you check for updates they will automatically be downloaded and extracted. Once they are ready to be installed the ReadyToBeInstalled event will be called. From there you can stop all running processes and threads in the service and finish the installation of the update:

static void auBackend_ReadyToBeInstalled(object sender, EventArgs e)
{
    // ReadyToBeInstalled event is called when
    // either the UpdateStepOn == UpdateDownloaded or UpdateReadyToInstall

    if (auBackend.UpdateStepOn == UpdateStepOn.UpdateReadyToInstall)
    {
        //TODO: Delay the installation of the update until
        //      it's appropriate for your app.

        //TODO: Do any "spin-down" operations. auBackend.InstallNow() will
        //      exit this process using Environment.Exit(0), so run
        //      cleanup functions now (close threads, close running programs,
        //      release locked files, etc.)

        // here we'll just close immediately to install the new version
        auBackend.InstallNow();
    }
}

After the update has completed your service will be restarted.

Make sure your service name is correct

If you're using the AutomaticUpdaterBackend in your service then you must ensure your service name is correct (and the same) in all your code. This means confirming your service name in at least 3 places (sometimes more):

  1. The YourServiceName.cs file. Open the service code file in your designer and set the "ServiceName" property:

    Setting the service name

  2. The YourServiceNameInstaller.cs file. Open the service installer code file and make sure the "ServiceName" property of the "ServiceInstaller" instance is set to the same service name you used elsewhere:

    Setting the installer service name

  3. The AutomaticUpdaterBackend class, and all other instances. In your service make sure the AutomaticUpdaterBackend class is using the correct service name:

    Setting the installer service name

If your service name is different in your service installer, and your various service code files, then this will cause problems in the updating. One such problem is your service will not re-start after a successful update or an error. There are other problems as well. This is why you must ensure you service name is correct in all places it's used.


For Console Apps

Using the AutomaticUpdaterBackend class in console apps is similar to how you use it in a Windows Service. The only differences are that you create the AutomaticUpdaterBackend instance in the Main() function of your app and you don't use the ServiceName property. For example:

auBackend = new AutomaticUpdaterBackend
                {
                    //TODO: set a unique string.
                    // For instance, "appname-companyname"
                    GUID = "a-string-that-uniquely-IDs-your-app",

                    // With UpdateType set to Automatic, you're still in
                    // charge of checking for updates, but the
                    // AutomaticUpdaterBackend continues with the
                    // downloading and extracting automatically.
                    UpdateType = UpdateType.Automatic
                };

Step 3: Events and properties

We talked about just one event, ReadyToBeInstalled, but there are many more. For instance, you should handle errors using the CheckingFailed, DownloadingFailed, ExtractingFailed, UpdateFailed.