# Wednesday, May 09, 2012
 #
Posted by Brian Haas on Wednesday, May 09, 2012
 

For applications that deploy a Windows Service, updating the installed service can present a maintenance challenge. This is a scenario where integrating AppLife Update makes a difficult task extremely easy to accomplish. Using AppLife Update actions, a Windows Service can be updated in three easy steps.

  1. Stop the Service using a Stop Service update action.
  2. Replace the Service assemblies using one of the available file replacement actions.
  3. Restart the Service using a Start Service update action.

Tada! Big maintenance challenge accomplished.

An Example

The release of AppLife Update 4.5 included a few very small changes to our AppLife Update Windows Service. Specifically, in previous versions, if the Windows Application Event Log was full and not configured to replace old events, our service would not apply an update. This issue affects a very small number of systems as since Windows Vista, the default logging behavior is to replace old log events when the event log is full, and the event log has to actually be full to cause an issue. For customers who use our AppLife Update Windows Service, if you choose, you can update the AppLife Update Windows Service on your deployed clients during your next application update. This is optional because if the logging issue isn’t a concern, you can leave the previous version alone. Any past version of the elevation service will operate properly with the latest AppLife Update controller. If you do so choose, here is how you can update the AppLife Update Windows Service (or any other Windows Service for that matter).

Stop the Service

To stop the service, we need to know the service name. If you don’t already know the name of the service you are updating, it can be found in the Services manager.

image

Open your application update project file (.aup). Add a Stop Service action to your update. Set the Service to Stop property to the name of your service. In this case, the service name is KjsUpdateService2.

image

Replace the Service Assemblies

We use an Add & Replace files on restart action to update the assemblies. The AppLife Update Windows service is initially deployed using an MSI merge module, and is always installed to the Common Files Folder\AppLifeUpdateService2 folder. To update the service, we’ll select the Common Program Files (x86) client folder and set the appropriate sub-directory, and then add the two assemblies that constitute the service. Choosing the x86 variant of the Common Program Files folder will ensure we target the x86 common files folder on x64 operating systems. Using the non x86 Common Program Files directory targets the x64 folder on 64-bit operating systems. On x86 operating systems, there is only one common program files directory, and either variant will target the correct folder.

image 

Note: When updating most Windows Services, even when a service updates itself, the service assemblies can be replaced immediately, without deferring to a restart. The AppLife Update service core assembly houses a class used to marshal information between the User Interface process and the service started worker process. For this reason, even though the service is successfully stopped, a lock is still being maintained on the core service assembly while the update is executed. Because this lock is not released until the update completes, the file replacement is deferred until restart. We do not need to force an operating system restart, as the previous update service can be restarted and function properly until the system is restarted. If a restart were necessary, we could include a Restart Operating System action to accomplish this.

The service assemblies ship with AppLife Update already embedded into the AppLifeUpdateService.msm merge module. After an installation, the assemblies will be in the common program files folder and can be extracted from there. After this action executes, the Windows Service will be updated. Now we just need to restart the service.

Restarting the Service

The service is restarted by adding a Start Service update action. The action is configured by defining the name of the service to restart. In this case it is again, KjsUpdatService2.

image

That’s it! Windows Service update completed.

But My Service is My Application?

This example assumes an existing update process exists and can be utilized to update the Windows Service. This is usually an installed application that utilizes the Windows Service, and can take responsibility for updating it. A stand-alone Windows Service can become “Self Updating” just as easily by integrating an update process using an AppLife Update controller. There is one point to make in this scenario. When applying an update, you want to use the option to instruct the update controller not to shut down the host application (the service). The Stop Service update action performs a proper service shutdown through the use of the Windows Service Control Manager, and is the recommended method to use when stopping a service for an update.

Wednesday, May 09, 2012
# Monday, April 30, 2012
 #
Posted by Brian Haas on Tuesday, May 01, 2012
 

In my previous post I used a callable action list along with Xml Update Actions to read all of the database connection strings identified in an app.config file, then iterate and update each one of the databases during an application update. The approach I took to accomplish the goal only used built-in Update Actions that are available to me in the Actions Palette. I purposefully chose not to use dynamic code actions (custom update actions) to make a point of what we can accomplish without resorting to writing our own code. However, what can be accomplished with a little custom code is extremely powerful, so now I’m going to revisit the objective, removing the intent of relying only on built-in actions.

Identifying the Databases to Update

In this scenario, the local databases that need to be updated during our application update are listed in the application configuration file. This is very convenient, especially when I want to use built-in actions to find the information. But what if the databases were not so conveniently discoverable? What if you first had to connect to a database server and search through all of the databases on the server for a specific naming convention? What if the databases were passed into the update process from the host application? Using a dynamic code action, scenarios like this can be easily handled.

Custom Update Actions and Shared Properties

The feature duo that makes what might initially sound difficult to accomplish during an application update magically easy using AppLife Update are Custom Actions and Shared Properties. Custom Actions are simply classes that inherit from an UpdateAction base class and implements at a minimum, an Execute method and a Rollback method. Shared Properties are a collection of objects that are scoped to the context of the update and can be accessed from any update action.

For our purposes, we want a custom update action that will read the list of databases from an application configuration file. The C#/VB.NET Code action lets me write this custom action directly within the update creation software.

Note:  Custom Actions can also be created in Visual Studio and compiled to an assembly.  Custom Action assemblies can be added to an update project through the Project..Settings dialog, or added the Custom Actions folder located within the AppLife Update install directory.

clip_image001

Here is the code:

Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using Kjs.AppLife.Update.Engine.Core;
  5. using System.Xml;
  6. using System.IO;
  7.  
  8. namespace DynamicCodeActions {
  9.     public class DynamicAction1 : UpdateAction {
  10.  
  11.         public override void Execute(UpdateContext context) {
  12.             //Read connection strings from app.config
  13.             XmlDocument configDoc = new XmlDocument();
  14.             configDoc.Load(Path.Combine(context.ApplicationDirectory, "CallActionListExample.exe.config"));
  15.  
  16.             XmlNodeList connStrings = configDoc.SelectNodes("/configuration/connectionStrings/*");
  17.             List<string> connectionStrings = new List<string>();
  18.             foreach(XmlNode node in connStrings) {
  19.                 connectionStrings.Add(node.Attributes["connectionString"].Value);
  20.                 context.Log.WriteLine(string.Format("Added connStr: {0}", node.Attributes["connectionString"].Value));
  21.             }
  22.             if(connectionStrings.Count > 0) {
  23.                 context.SharedProperties.Add("ConnectionStrings", connectionStrings);
  24.                 context.SharedProperties.Add("ExecuteDBUpdate", true);
  25.                 context.SharedProperties.Add("CurrentConnectionString", "");
  26.             } else {
  27.                 context.SharedProperties.Add("ExecuteDBUpdate", false);
  28.             }
  29.         }
  30.  
  31.         public override void RollbackExecute(UpdateContext context) {
  32.             //Add code here to undo work that was performed in the Execute
  33.             //method.  The method is not performed if the Execute method
  34.             //is not completed.
  35.  
  36.             context.SharedProperties.Remove("ConnectionStrings");
  37.             context.SharedProperties.Remove("ExecuteDBUpdate");
  38.  
  39.  
  40.         }
  41.     }
  42. }

Notice that through the context parameter, the code can access the Shared Properties collection as well as other properties, such as the physical path to the host application. This code simply opens the application configuration file and reads the database connection strings. These strings are then added to a generic List of strings, and that List is added to the Shared Properties collection. If the list is not empty, another Shared Property is added that will be used in a conditional statement.

Manipulating the List from other Actions

With the list of database connection strings in the Shared Properties collection, we can call the recursive callable update action list to update the databases. This in-memory list takes the place of the copied app.config file used in the original post. From within the Update Databases action list, we can read and manipulate the Shared Properties collection with other custom update actions.

Read the Next Connection String

clip_image002

Remove the Item after the Database is Updated

clip_image003

Conclusion

Using Update Actions and Shared Properties during an application update allows you to very easily accomplish complicated processing on deployed clients. The C# / VB.NET update action lets you add your own code logic to your update, and using Shared Properties, your code can easily interact with built-in actions as well as other custom actions.

Download Example AppLife Update Project

Tuesday, May 01, 2012
# Friday, April 20, 2012
 #
Posted by Brian Haas on Friday, April 20, 2012
 

The recently released AppLife Update 4.5 includes many new features, one of which is the ability to create independent, callable action lists. By combining callable action lists with Shared Properties and applying conditional statements to update actions we can more easily accomplish advanced updating activity. One scenario which we can use to demonstrate this functionality is when an application uses multiple local databases. In order to update the installed application, all of the databases that are present must be updated. In this scenario an update will need to be able to:

1. Identify all of the databases that are present.

2. Iterate each of the local databases, applying the necessary change script to each one.

3. Update the application assemblies.

For this example, the list of databases will be discovered by inspecting the application configuration file. Each database connection string is listed in the connectionStrings segment of the configuration file. For each of the listed databases, we’ll connect to the database, start a transaction, run a SQL script, commit the transaction and close the connection.

Note that all of the update actions and logic is packaged into a single, stand-alone update package. The update process embedded into the application discovers the new update, downloads it, and then initiates it. Once initiated, the Update Engine executes the update actions that perform the work. This example focuses completely on the update actions. No mention is made of the update process integrated into the application.

Identify and Manage the Local Database List

To read the databases that are present and manage the list as the databases are updated, I am going to read an item from the connectionStrings configuration element, update the database identified within it, and then remove the element from the configuration file. Using this method, I can accomplish all of the work using built-in update actions. This is not the only option available. Using Dynamic Code Actions offers more flexibility and an alternative approach. I’ll perform the same work using Dynamic Code actions in my next blog post.

Now, I mentioned that as we update the databases I am going to remove the element from the config file. We don’t want to modify the actual application configuration file so the first thing that I am going to do is copy the config file to the working update directory. This is a directory created by the update engine and it is deleted when the update ends. I’ll accomplish this by using a Run command line update action. This action includes a helper feature that allows us to use common directories to define two path variables. The Application Directory is the physical path of the application that launched the update. This is where the application configuration file resides. The Update Package Directory is the physical path to the temporary working directory that is created for this update by the update engine. I define <path1> to be the path to the application configuration file, and I define <path2> to be the path of my copy of the config file. I’ll call it config.xml. With the two paths specified, I’ll use them in the actual command line that copies the config file:

copy “<path1>” “<path2>”

clip_image001

To read the entries in the config file, I’ll use a Read Xml Node action. To use this action we specify an Xml file to read, define an XPath expression to identify the node value we are interested in, and then provide a name of a Shared Property to hold the string value of the Xml Node. The Shared Property can then be accessed and used by other actions as well as in conditional statements. I’ll be doing both with this Shared Property.

clip_image002

Here is what the config file section looks like:

<configuration>

<connectionStrings>

<add name="Db1" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=TestDb1;Integrated Security=True"/>

<add name="Db2" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=TestDb2;Integrated Security=True"/>

</connectionStrings>

</configuration>

I am interested in the connectionString, so my XPath expression is /configuration/connectionStrings/add/@connectionString

If multiple nodes are found, the action is configured to read the first node, and if no node is present a default value of None is assigned. We’ll use this in a conditional statement. If a node is present, a Shared Property with a key of ConnStr will be populated with a local database connection string. Next we’ll use a callable action list to update this database using SQL Server update actions, remove the connection string from our working config file, and recursively call itself until all of the databases represented in the config file are updated. If the ConnStr Shared Property does not equal the value “None”, we call the action list.

clip_image003

Update the Database

The databases I am updating are SQL Server databases. Therefore I am using the SQL Server Update Actions that are also new to AppLife Update 4.5. Note that there are separate provider-Independent database actions available that can be used for updating any type of database. Using the SQL Server Actions, for each database we are going to:

1. Open a Database Connection. I’ll configure the action to place the database in single-user mode.

2. Begin a SQL Server Transaction.

3. Execute a database query.

4. Commit the SQL Server transaction

5. Close the SQL Connection

To open the connection, I set the connection string directly, and then use the ConnStr Shared Property we already defined. For many built-in actions, you can use Shared Properties that are strings by using a $SharedPropertyKey$ syntax. Wherever this is used, the Shared Property string value is expanded in-line during update execution. Notice that the connection itself is added to the Shared Properties collection using the defined key. Here the key is named SqlConection. We’ll use this Shared Property in the other database actions.

clip_image004

With a SQL Connection open, I’ll start a transaction using the Begin SQL Server Transaction action. To use this action we specify the connection to use and provide a Shared Property key name for the transaction. The transaction Isolation Level can also be specified. If the update fails, this transaction will be rolled back automatically unless the transaction is committed by a Commit SQL Server transaction action.

clip_image005

With the transaction started, it can be used by one or more Run SQL Server query actions. In this example, I’ll just add a table.

clip_image006

Next, I’ll commit the SQL transaction and close the database connection. Taking this approach means that should any of the database updates fail, the database changes made in all previously updated databases would not be rolled back because they have already been committed. I chose this approach for simplicity, however the update could be refactored to maintain all transactions open until all of the databases have been updated, then iterate the transactions and commit each one. Using this alternate approach, should any SQL query fail, all databases would roll back their changes.

clip_image007

Closing the connection by specifying the Shared Property key…

clip_image008

Remove the Database from the Working Xml File

With the designated database updated, I am going to remove the connection string from the working Xml file using a Delete Xml Node action. To use this action, I specify the Xml file and as XPath expression identifying the node of interest, just like we did when defining the connection string. The node we are interested in is the connection string entry with the attribute value that matches the connection string of the database that we just updated.

clip_image009

With the node removed from the working file, we’ll again use a Read Xml Node action to read the next connection string in the file. If there is another connection string available, we’ll assign it to the ConnStr Shared Property. Otherwise, just like before, if no connection strings are left the value of the Shared Property will be set to “None”.

clip_image010

And now as long as the value of the ConnStr Shared property is not “None” we’ll call this same action list again, updating the next database in the list.

clip_image011

This process is repeated for all of the databases identified in the connectionStrings configuration element.

Replace the Application Assemblies

To complete this update, I’ll use an Add & Replace Files action to replace the main application executable.

clip_image012

Summary

By using the new callable action list feature and the Shared Properties collection, we are able to read the list of local databases from the application configuration file and iteratively update each one. The new features of AppLife Update 4.5 provide more power and flexibility while maintaining the robust, transactable operation of the AppLife updating engine. In a follow-up blog post, I’ll use Dynamic Code actions and custom C# code instead of Xml Actions to read the connection strings and use a collection object instead of a temporary file to manage the databases.

Download Example Project

View Execution Log

Friday, April 20, 2012
# Wednesday, March 21, 2012
 #
Posted by Brian Haas on Wednesday, March 21, 2012
 

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.  
  13.                 BackgroundWorker worker = new BackgroundWorker();
  14.                 worker.DoWork += new DoWorkEventHandler(worker_DoWork);
  15.                 worker.RunWorkerAsync(updateController1);
  16.                 ApplicationUpdateInitiatedDialog dlg =
  17.                 new ApplicationUpdateInitiatedDialog(true);
  18.                 dlg.ShowDialog(this);
  19.             }
  20.         }
  21.     }
  22.  
  23.     private void worker_DoWork(object sender, DoWorkEventArgs e) {
  24.         //Since the ApplyUpdate method call is a
  25.         //blocking call, and we want the UI to remain
  26.         //response as the user waits for all instances
  27.         //to close, we'll initiate the update on a
  28.         //background thread.
  29.  
  30.         UpdateController controller = e.Argument as UpdateController;
  31.         if(controller != null) {
  32.             controller.ApplyUpdate(ApplyUpdateOptions.AutoClose);
  33.         }
  34.     }
  35.  
  36.     private void updateController1_UpdateStarting(object sender,
  37.             UpdateStartingEventArgs e) {
  38.         //An update has been an initated and this
  39.         //application will shutdown. This dialog will
  40.         //inform any other users that the application
  41.         //is about to shutdown on them. Showing this
  42.         //dialog is import for Terminal Services
  43.         //installations. Note: It is possible to
  44.         //allow other users to cancel the ongoing
  45.         //update process
  46.  
  47.         //This dialog is shown for 5 seconds
  48.         //before it is closed automatically
  49.         if(!e.IsInitiatingController) {
  50.             ApplicationUpdateInitiatedDialog dlg =
  51.         new ApplicationUpdateInitiatedDialog(false);
  52.             dlg.ShowDialog(this);
  53.         }
  54.     }
  55. }

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.

clip_image001

Download Terminal Services Example Project

Wednesday, March 21, 2012
# Friday, February 10, 2012
 #
Posted by Brian Haas on Friday, February 10, 2012
 

The ability to organize and define software requirements using AppLife DNA just got better! We’ve released version 3.0 of AppLife DNA and with this release comes an exceptional user interface mockup designer and collaborative online reviews.

The AppLife DNA Mockup Designer

Mockups are a major component of defining and designing software systems and having the ability to quickly insert and create screen mockups directly within AppLife DNA significantly improves your ability to communicate your ideas and the details of your requirements elicitation work.

image

Insert and Configure User Interface Elements

With the new AppLife DNA Mockup Editor, creating screen mockups is a breeze. Simply drag and drop the visual objects that you are already familiar with from the palette. Mockup visuals are configured using simple text phrases and click-able adornments. There are over 50 mockup visuals ready to use, with more to come. The mockup designer has an image gallery with 100's of images , and gallery images can be inserted into visual controls by using their names in parentheses.

clip_image003clip_image004

Arrange and Align Elements

User interface elements can be quickly aligned using snap-lines and familiar alignment commands.

clip_image005clip_image007

Elements can also be grouped, so that they can be manipulated as a single unit. Container controls, such as forms, tabs and panels, utilize implicit grouping providing the ability to move all of their contents around along with the container without having to create explicit groups to do so.

Start From Existing Screens

Get started quickly mocking up new features to existing applications by taking a screen shot and then paste it right into the mockup editor. Can you spot the mocked up content below?

clip_image008

Watch a mockup being created

Using mockups instead of hand sketches to prototype user screens lets you quickly modify the mockup based on feedback. And speaking of feedback, we've introduced a brand new way to solicit stakeholder feedback with AppLife DNA Online Reviews.

AppLife DNA Online Reviews

You’ve gathered requirements, elaborated some details, described the features and mocked up some screens. Now you need stakeholder feedback to validate your understanding and move forward. Getting stakeholder feedback at this point, when it is still cheap to change things is essential. AppLife DNA Online Reviews helps you get it.

With AppLife DNA Online Reviews you can publish any content in AppLife DNA to the Online Review Service and invite up to 20 stakeholders to participate in a short duration (1 - 14 days) online collaborative review session. We've made it as painless as possible for your stakeholders. No account or licensing needed, just an email address and an interest in the content you have published. Your stakeholders receive an email invitation with a link, where they can enter the review session, review your work, read everyone's comments and post comments themselves.

clip_image009

Reviewers can leave page comments, highlight and strike through text, and use digital ink for comments. When the review closes, return to AppLife DNA where you can use this valuable feedback to modify your content as necessary. With Online Reviews, everyone reviews your content at the same time and sees everyone's comments, which drastically speeds up the process and improves the quality of the feedback. It's a very quick and painless method to solicit feedback.

Passcode Encryption

For users who are concerned with publishing sensitive requirements information to the cloud, we've taken a big step towards alleviating this concern. When content is published to the Online Review system, you can choose to protect the review with a passcode. If a passcode is provided, the published document and all comments are encrypted using the passcode before being sent to the Online Review Service. The passcode is never transmitted and no one who doesn't know the passcode will ever be able to decrypt and review the published content.

Short Durations for Fast Turnaround

Online Review durations are short, usually only a few days. This encourages stakeholders to contribute now, not later, and also encourages collaborative back and fourth feedback. When a review closes, the Online Review service keeps the content only long enough for the publisher to retrieve the information from AppLife DNA, and then disposes of all published data. Online Reviews live for a short, sweet, and effective period of time.

The Online Review service can be used during the AppLife DNA 30 day evaluation period, so download AppLife DNA and check out this exciting new method of soliciting requirements feedback today!

Friday, February 10, 2012