The AppLife Update Blog

  • Available Updates .aspx Page

    As you publish updates using AppLife Update, the information about the available updates is available to your deployed applications. Using the Update Controller, your deployed applications can easily check for updates over http, ftp, unc, or file path. Using the Update Controller, you can investigate the available updates programmatically through the Update Controller API. But what about presenting a list of available updates to a human user via a web page? Shouldn’t that be just as easy? Turns out, it is, but it doesn’t appear so at first glance.

    Let’s instantiate an Update Controller in an aspx page code behind and see what happens.

       1:  protected void Page_Load(object sender, EventArgs e) {
       2:    using(UpdateController controller = new UpdateController()) {
       3:      //all we need to just check for updates is an update location and application id
       4:        controller.UpdateLocation = "http://localhost/updates/myapp";
       5:        controller.ApplicationId = new Guid("288b93ae-0795-47bf-959e-06dc96434d43");
       6:   
       7:        if(controller.CheckForUpdate()) { 
       8:          //display update information
       9:        }
      10:    }
      11:  }

    We get an ugly error about starting an asynchronous operation.

    image

    Download the attached aspx form and code-behind for a complete working example.

    image

    Even though the CheckForUpdate method is synchronous to the calling code, it uses an asynchronous method under the hood and the asp.net page doesn’t like that. To get around this, we’ll use a PageAsyncTask object to execute the update check between the page prerender and prerender complete processing steps. To accomplish this, we’ll move our update checking code to its own method, and then create and register a PageAsyncTask to execute it.

       1:  protected void Page_Load(object sender, EventArgs e) {
       2:    PageAsyncTask asyncTask = new PageAsyncTask(
       3:             new BeginEventHandler(BeginCheckForUpdate),
       4:             new EndEventHandler(EndCheckForUpdate),
       5:             new EndEventHandler(CheckForUpdateTimeout), null);
       6:              
       7:    RegisterAsyncTask(asyncTask);
       8:  }
       9:   
      10:  IAsyncResult BeginCheckForUpdate(object sender, EventArgs e, AsyncCallback cb, object state) {
      11:    return null;
      12:  }
      13:   
      14:  void EndCheckForUpdate(IAsyncResult ar) {
      15:               
      16:  }
      17:   
      18:  void CheckForUpdateTimeout(IAsyncResult ar) {
      19:               
      20:  }
      21:   
      22:  private void checkForUpdate() {
      23:    using(UpdateController controller = new UpdateController()) {
      24:      //all we need to just check for updates is an update location and application id
      25:      controller.UpdateLocation = "http://localhost/updates/myapp";
      26:      controller.ApplicationId = new Guid("288b93ae-0795-47bf-959e-06dc96434d43");
      27:   
      28:      if(controller.CheckForUpdate()) {
      29:        //display update information
      30:      }
      31:    }
      32:  }

    The code above gets us almost there. We have an asynchronous task plumbed in, but because the controller’s CheckForUpdate method isn’t really an asynchronous method, we don’t have an IAsyncResult interface readily available to plug into the async task. If we use a delegate method, we can slip our “synchronous call” into an asynchronous context.

       1:  public partial class AvailableUpdatesPage : System.Web.UI.Page {
       2:    private Action mCheckForUpdateWork; //Use a delegate for IAsyncResult context
       3:   
       4:    protected void Page_Load(object sender, EventArgs e) {
       5:      PageAsyncTask asyncTask = new PageAsyncTask(
       6:                        new BeginEventHandler(BeginCheckForUpdate),
       7:                        new EndEventHandler(EndCheckForUpdate),
       8:                        new EndEventHandler(CheckForUpdateTimeout), null);
       9:   
      10:      RegisterAsyncTask(asyncTask);
      11:    }
      12:   
      13:    IAsyncResult BeginCheckForUpdate(object sender, EventArgs e, AsyncCallback cb, object state) {
      14:      mCheckForUpdateWork = new Action(checkForUpdate);
      15:      return mCheckForUpdateWork.BeginInvoke(cb, state);
      16:    }
      17:   
      18:    void EndCheckForUpdate(IAsyncResult ar) {
      19:      mCheckForUpdateWork.EndInvoke(ar);    
      20:    }
      21:   
      22:    void CheckForUpdateTimeout(IAsyncResult ar) {
      23:      mCheckForUpdateWork.EndInvoke(ar);
      24:    }
      25:   
      26:    private void checkForUpdate() {
      27:      using(UpdateController controller = new UpdateController()) {
      28:        //all we need to just check for updates is an update location and application id
      29:        controller.UpdateLocation = "http://localhost/updates/myapp";
      30:        controller.ApplicationId = new Guid("288b93ae-0795-47bf-959e-06dc96434d43");
      31:         
      32:        if(controller.CheckForUpdate()) {
      33:          //display update information
      34:        }
      35:      }
      36:    }
      37:  }

    All that’s left to do is set the Async page directive to true and this page will successfully perform an update check, where we can then use the controller API to manipulate the display of the available information.

    <%Page Language="C#" AutoEventWireup="true" CodeBehind="..." Inherits="..."
     Async="true" AsyncTimeout="30"%>

    The example page creates an asp.net Repeater object to format and display each of the available updates on the web page. We can then simply DataBind the AvailableUpdates collection of the update controller to the repeater.

       1:  if(controller.CheckForUpdate()) {
       2:    //display update information
       3:    rptrUpdateList.DataSource = controller.AllUpdates;
       4:    rptrUpdateList.DataBind();
       5:  }

    Posted at 31 October, 2013 | By :Brian Haas | Categories : AppLife Update |
  • Expand Update Possibilities with Manual Versioning

    AppLife Update identifies the existence of an update through the use of versioning. The update controller deployed out there on client systems knows the current version that is installed and, after performing an update check, knows the update packages that have been published for the current version. With this information, the process can continue. Most commonly, a deployed client’s current version is determined by the .Net Assembly Version stamp of the host .Net executable. Using an assembly version, the current version is readily available, and when the host executable is replaced, presumably the replacement executable has a new higher assembly version. The AppLife Update solution makes it very easy to use the .Net Assembly Version stamp in a very hands-off way, making it the most common scenario. It is not the only method available though, and looking at versioning a little differently opens up many possibilities.

    What’s Possible with Custom Versioning

    The thing about using an Assembly Version stamp is that the executable must be rebuilt in order to create an update. There are circumstances where it is favorable to be able to update an application installation without rebuilding the primary executable. Sometimes what you might want to update isn’t even an application at all. AppLife Update can be used to package and automatically deploy updates to all kinds of application sub-systems, such as reporting templates, map files, and other types of document repositories. The ease with which you can package any information, as well as a code process to execute, into an update package and the flexibility available to implement a simple check, retrieve, and apply process using an AppLife Update Controller makes it possible to be very creative with updating application components independently. Versioning is key to any update process using AppLife Update, so here is a simple and effective method for versioning just about any type of update process.

    Xml File Versioning

    The basic idea behind Xml File Versioning is to place a simple Xml file on the client PC that holds a version stamp. We’ll read that version stamp from the file and set the Update Controller version based on the content so that we can publish updates that target a specific version. Within the update, we’ll use an Xml Update Action to modify that version file contents so that after the update is executed, the version file will then represent a newer version based on the modifications that the update made.

    Note: We will use a stand-alone Xml file, however applications that utilize a .config already have an Xml file readily available for versioning sub-components. Adding a new appSettings value to an existing .config file can accomplish the same result.

    We’ll need a snippet of Xml to hold a version stamp. A file like this will do just fine:

    Filename: Version.Xml

    <?xml version="1.0" encoding="utf-8"?>
    <version>
        <currentVersion value="1.0.0.0" />
    </version>

    Read the Current Version and Setup the Controller

    To setup an Update Controller for manual versioning, ensure the UseHostAssemblyVersion property is set to false. With that set, your code can set the Version property based on the content of the Version.Xml file.

    private Version getCurrentVersion() {

      Version currentVersion = null;
        using(XmlReader reader = XmlReader.Create("Version.Xml")) {
          reader.ReadToFollowing("currentVersion");
          string versionStr = reader.GetAttribute("value");
          if(!string.IsNullOrEmpty(versionStr)) {
            currentVersion = new Version(versionStr);
          }
        }
      return currentVersion;
    }

    With the version set, you can call CheckForUpdate or CheckForUpdateAsync on the Update Controller and find updates for the current client version.

    Applying Updates without Shutting Down the Host Application

    When updating sub-systems, it is often not necessary as well as undesirable to shut down the host application. If the update will operate on files that are not locked, or can be unlocked without shutting down the application, your sub-system updating process can operate seamlessly by using a few of the options that are available when applying an update. To accomplish this, pass in a parameter to the ApplyUpdate method. The following options will apply an update without shutting down, without showing an update window (silently), and the method call will wait for the update to complete (synchronously). Any combination of these options can be used.

    mUpdateController.ApplyUpdate
    (ApplyUpdateOptions.NoShutdown | ApplyUpdateOptions.NoUpdateWindow |
    ApplyUpdateOptions.WaitForCompletion);

    Updating the Version.Xml file during an Update

    Maintaining the Version.Xml file is very easy and once we set it up, we can forget about it. Each update will modify the version file based on the update version that is being executed. We can accomplish this by adding two update actions to the update action list.

    1. Use a Set Shared Property update action to access the current update version value and assign it to a Shared Property.

    2. Use a Change Xml Node update action to modify the Version.Xml file on the client to match the current update version.

    Action 1

    clip_image001

    Action 2

    clip_image002

    That’s it. Precede these two actions with the update actions that perform the necessary work on the client and proceed to publish updates that your application can find and seamlessly apply. An Update Controller and manual versioning opens the door for many creative updating scenarios utilizing the power and flexibility of the AppLife Update engine.

    Posted at 28 September, 2012 | By :Brian Haas | Categories : AppLife Update |
  • Application Update Customization using Custom Data

    When publishing updates for applications, it is often helpful to implement rules that can be applied on an update-by-update basis. With AppLife Update, the custom data field provides this opportunity.

    clip_image001

    With each update, you can specify a custom data string to go with the update. This value is then available to your application after an update check has been performed. Your application can interrogate the value and control additional logic based on the information. As an example, when creating updates for AppLife Update, we use this field to know whether or not the update requires Visual Studio to be closed. If it does, we add a RequiresVSClosed property to the custom data field.

    Accessing the Custom Data in Your Application

    After an update check, the update controller has a CurrentUpdate property that holds an UpdateInformation object. This object has a CustomData property that holds, you guessed it, the Custom Data string that you specify when publishing the update.

     

    Code Snippet

    1.if(updateController1.CheckForUpdate()) {

    2.   string customData = updateController1.CurrentUpdate.CustomData;

    3.}

    Changing Custom Data after Publication

    Custom Data can be modified after an update has been published without having to re-build the update package itself. To modify custom data, you can Manage Published Updates…

    From the Manage Published Updates dialog the Custom Data string can be modified and then published.

    clip_image002

    A Class to Parse Name/Value Pairs

    A common approach to be able to provide multiple pieces of information through the custom data string is to use a name/value pair syntax, and then extract this information within your application code. To help with this, here is a class that will parse a custom data field using a name=value; syntax.

    AppUpdateCustomData.cs and AppUpdateCustomData.vb

    Using this class, you can easily extract and use multi-value custom data strings in your applications.

    clip_image003

    Using the AppUpdateCustomData class:

     

    Code Snippet

    1.  if(updateController1.CheckForUpdate()) {

    2.    Kjs.AppLife.Update.AppUpdateCustomData customData = new Kjs.AppLife.Update.AppUpdateCustomData(updateController1.CurrentUpdate.CustomData);

    3.   

    4.    string myValue1;

    5.    string myValue2;

    6.   

    7.    if(customData.DataTable.ContainsKey("MyName1")) {

    8.      myValue1 = customData.DataTable["MyName1"];

    9.    }

    10. 

    11.  if(customData.DataTable.ContainsKey("MyName2")) {

    12.    myValue2 = customData.DataTable["MyName2"];

    13.  }

    14.}

    In conclusion, the Custom Data field provides the means for update publishers to assign information to individual update packages that applications can use to control application update behavior.

    Posted at 18 September, 2012 | By :Brian Haas | Categories : AppLife Update | Software Updating |
  • Using a Pre-Build Script for File Automation

    When an application update is built with AppLife Update, you can define a pre-build and post-build batch script to run during the build process. This ability to easily interact with the build process provides, among other things, the means to move files around on the build system before the actions in the action list are built. This allows for accomplishing automation tasks that might otherwise require a custom action builder. Action builders are more powerful, but more technically complicated as well. Creating a pre-build script is easy. In this post, I will demonstrate the use of a pre-build script to remove the necessity of manually modifying an action configuration before building an update.

    Hub and Spoke Update Deployment Example

    The Hub and Spoke Update Deployment solution lab outlines how AppLife Update can be used to “update” multiple application update servers. This is a part of a process that allows a software publisher using AppLife Update to maintain many remote update servers for their applications. With remote update servers, client systems can check for and retrieve updates from servers that are on their local networks, instead of from a global update server over a wide area network.

    The update actions that maintain those remote application update servers simply add two files to the update. The first file is the Director.Xml document, and the second file is the newest update package built for the application. This file is named major.minor.build.revision.zip based on the current version number of the application. The issue here is that the version number always changes, and when a standard Add & Replace Files action is utilized, the action configuration must also change with each new update in order to address the proper update package.

    clip_image001

    With a little help from the pre-build batch script and using a different update file action, we can remove this requirement to manually modify the update configuration with each update, which makes creating the remote server update a one-step process using the AppLife Make Update tool. Configured this way, the remote server update build can also be easily incorporated into a larger automation process using the Command Line build utility.

    The Pre-Build Script

    The project pre-build script can be accessed from the project settings dialog, under the build tab. When creating a pre/post build script, there are replacement values that can be inserted into the script. Replacement values provide access to contextual information from the update project. We’ll be taking advantage of the $UpdateVersion$ and $ProjectDirectory$ replacements to accomplish the goal.

    The goal of the pre-build script is to empty a working folder, and then add the two files that will be included in the update to the working folder. The two files will be the Director.Xml file and the application update package that matches the designated update version. The script will copy these files from a local folder that represents the primary application update folder, and will be addressed in the script using a relative file path from the current AppLife Update project file location. After the pre-build script runs, there will be a working directory that contains two files. The Director.Xml file and the application update package (a.b.c.d.zip) file that matches the defined update version number. Then, we just need to use an update action to add these files to the update. Here is the script.

    Set WorkingPath=$ProjectDirectory$\Current Update

    Set AppUpdatePath=$ProjectDirectory$\..\Application Updates

    Del %WorkingPath%\*.*

    Copy "%AppUpdatePath%\Director.Xml" "%WorkingPath%"

    Copy "%AppUpdatePath%\$UpdateVersion$.Zip" "%WorkingPath%"

    Using replacements, we have access to the version number of the update currently being built, and we also have access to the path of the .aup AppLife Update project file. We use this information to copy the correct update package from the correct folder.

    The Update Actions

    With the pre-build script, the files that we want to add to the update is going to be sitting in a folder named Current Update that is a sibling to the AppLife Update .aup project file. Normally, we wouldn’t care which order the files are copied during the update, and the most obvious update action to use would be the Add Folder Content action. This action would simply add both of the files to the update as the update is built, and then write them to the designated client directory as the update engine executes the action on deployed clients. In this case though, we do care about order. We want the update package file copied first, and then the Director.Xml file. Because of this, we’ll use the Masked Add & Replace files action. With this action, we can apply a mask to the files that will be added to the update package. The first action will add the update package, and the second action the Director file. By applying a mask of (*.zip), the update package is added to the update.

    clip_image002

    To add the Director.Xml file to the update, we could have chosen the Add & Replace Files action, but for consistency we use another Masked Add & Replace action with a mask of *.Xml.

    With these two actions in place, the appropriate update package file and the corresponding Director.Xml file is added to the update package and will be placed in the application updates folder on remote update servers. To publish an update, no changes are necessary to the update project. We simply open AppLife Update and walk through the publish wizard. When the update version is defined in the wizard, the correct application update package is automatically included.

    Posted at 28 August, 2012 | By :Brian Haas | Categories : AppLife Update | Software Updating |
  • Enabling .Net 3.5 on Windows 8 During an Application Update

    In Windows 8, the .Net Framework 3.5 is not installed by default, however Windows 8 includes a Feature on Demand (FoD) option for the earlier frameworks.

    clip_image001

    We can enable this feature during an application update by using the Deployment Image Servicing and Management utility (dism). During an application update, we’ll execute the following command line:

    dism /online /enable-feature /featurename:NetFX3 /all /NoRestart /Quiet

    We can use a Run Command Line update action to perform the work. We just need to ensure that the update has elevated permissions. If you are already configured for update elevation, either by use of the AppLife Update Windows service or by the UAC, this is already taken care of. If however, your normal updates are not elevated, then you must explicitly set this update to elevate via the UAC when you publish the update.

    Configuring the Update

    To accomplish the goal, we’ll create an action list and name it Win 8 FX 3. In this action list, we’ll add:

    • Run Command Line action
    • Restart Operating System action
    • Prevent application restart action

    Run Command Line

    This action will run the dism command. This command requires an operating system restart, so we’ll explicitly command not to restart, and then let the update take care of this using a Restart Operating System action.

    clip_image002

    Note that this action takes some time to complete.

    Restart Operating System

    This command will prompt the user that a restart is required.

    clip_image003

    Prevent Application Restart

    If the host application will ordinarily restart after the update completes, we can suppress this knowing that the operating system must be restarted to complete the update. Depending on the host configuration, this action might or might not be necessary.

    clip_image004

    Conditionally Execute the Action List

    We only want to run this action list if the host operating system is Windows 8 and the .Net Framework 3.5 is not already installed. So from the primary action list, we’ll detect the OS version and .Net Framework 3.5 install state, and then run the Win 8 FX 3 action list only when necessary. To detect the OS version, we use a Read Registry Value action to read and assign the OS version to a Shared Property we’ll name WinVersion.

    image

    To detect the .Net Framework install state, we’ll inspect another registry key.  Note that the dism tool can retrieve information on Windows features using the Get command, however using that approach would require code to parse the command return information.Reading directly from the registry doesn’t require any parsing code.

    image

    These shared properties can then be used as a condition to run the Win 8 FX 3 action list.

    image

    That completes the configuration of the update. Now all we need to do is ensure that the update will run elevated, if your application isn’t already set up to ensure this. When publishing, we can set this update to use the UAC for permissions elevation.

    Ensure Elevation for this Update

    clip_image007

    The host for this update must be capable of running on the .Net 4.0 framework, as this will be available on Windows 8 out of the box. After running this update, executables that target the .Net 2.0 through 3.5 framework will be able to run on the deployed system.

    Posted at 3 August, 2012 | By :Brian Haas | Categories : AppLife Update | Software Updating |