The AppLife Update Blog

A complete solution for maintaining deployed software on the Windows platform

  • Terminal Services Application Updating

    The AppLife Update solution is a perfect fit for maintaining applications that operate in multi-user terminal services environments. In a terminal services installation, there are likely many users simultaneously running your application. Application maintenance solutions must account for the fact that there can be multiple instances of an application running at one time as any running instance will maintain a lock on files and assemblies that must be replaced during an update process. The AppLife Update Solution ensures that all running instances of an application are shutdown prior to starting an update, and this is accomplished through a built-in Inter-process communications (IPC) feature. The IPC employed within AppLife Update communicates across all users and will shut down all instances of an application running in a terminal services environment, making the solution a perfect fit for maintaining terminal services hosted applications.

    Out of the box, AppLife Update will shut down all instances of an application and allow you to update a terminal services application. There is however some customizations that can be applied to an application that is known to be targeting terminal services that will improve the users application updating experience.

    Terminal Services Application Updating with AppLife Update

    User Experience Customizations

    The AppLife Update API provides an opportunity for the integrating developer to interact with the IPC process and update initiation (starting) procedure. We can use this opportunity to improve the user experience. For the instance that initiated the update, we’ll display an indeterminate progress dialog as all instances are being shut down, and for the non-initiating instances, we’ll display an informative dialog for a short period of time indicating that the application is about to be closed for maintenance. Further enhancements could allow terminal services users to cancel the update process, or perform additional work before the shutdown.


    Code Snippet

    1:  private void checkForUpdatesToolStripMenuItem_Click_1(object sender,  
    2:        EventArgs e) {  
    3:      if(updateController1.ShowCheckForUpdateDialog(this,  
    4:        ErrorDisplayLevel.ShowExceptionMessage) == DialogResult.OK) {  
    5:        if(updateController1.ShowDownloadUpdateDialog(this,  
    6:          ErrorDisplayLevel.ShowExceptionMessage) == DialogResult.OK) {  
    7:          //Launch the update from another thread  
    8:          //To better accomodate terminal services  
    9:          //installations, the UI will remain  
    10:          //responsive as all of the other  
    11:          //instances of the application are closed.  
    12:          BackgroundWorker worker = new BackgroundWorker();  
    13:          worker.DoWork += new DoWorkEventHandler(worker_DoWork);  
    14:          worker.RunWorkerAsync(updateController1);  
    15:          ApplicationUpdateInitiatedDialog dlg =  
    16:          new ApplicationUpdateInitiatedDialog(true);  
    17:          dlg.ShowDialog(this);  
    18:        }  
    19:      }  
    20:    }  
    21:    private void worker_DoWork(object sender, DoWorkEventArgs e) {  
    22:      //Since the ApplyUpdate method call is a  
    23:      //blocking call, and we want the UI to remain  
    24:      //response as the user waits for all instances  
    25:      //to close, we'll initiate the update on a  
    26:      //background thread.  
    27:      UpdateController controller = e.Argument as UpdateController;  
    28:      if(controller != null) {  
    29:        controller.ApplyUpdate(ApplyUpdateOptions.AutoClose);  
    30:      }  
    31:    }  
    32:    private void updateController1_UpdateStarting(object sender,  
    33:        UpdateStartingEventArgs e) {  
    34:      //An update has been an initated and this  
    35:      //application will shutdown. This dialog will  
    36:      //inform any other users that the application  
    37:      //is about to shutdown on them. Showing this  
    38:      //dialog is import for Terminal Services  
    39:      //installations. Note: It is possible to  
    40:      //allow other users to cancel the ongoing  
    41:      //update process  
    42:      //This dialog is shown for 5 seconds  
    43:      //before it is closed automatically  
    44:      if(!e.IsInitiatingController) {  
    45:        ApplicationUpdateInitiatedDialog dlg =  
    46:      new ApplicationUpdateInitiatedDialog(false);  
    47:        dlg.ShowDialog(this);  
    48:      }  
    49:    }  
    50:  }  


    Prevent Users from Restarting During the Update

    During the actual update, the application files must be unlocked, and remain unlocked throughout the process. If a terminal services users attempts to start the application using their application shortcuts, the application assemblies could become locked and prevent the update form succeeding. To prevent this, we’ll make the first action taken during the update be to rename/remove the launching executable. If the launching executable is to be replaced during the update process, we’ll perform this action as the last step of the update. By taking this action, terminal services users will not be able to launch the application during the update process from existing shortcuts.


    Download Terminal Services Example Project

    Posted at March 21, 2012 | Categories : AppLife Update, Software Maintenance |