I am working on a project that is turning out the builds, sometimes with just a single change in an assembly (we are in bug fixing mode).  Doing a full install each time is tedious given that it is a server application with a Windows service, several configuration tools, three Microsoft Office Project Server event handlers, and quite a few dependant assemblies.  Manually hunting through the server replacing files got old and batch files assumed knowledge about target directories and other configuration information.  I decided to build a patching tool to ease the pain a bit.   I call it QuickPatch.  Last week I wrote about a new GUI for IExpress, which is the foundation on which QuickPatch is built.  Read about IExpress here.

Requirements

QuickPatch was designed to meet the following requirements:

  • Create a tool that generates self-extracting executables (SEE) taking advantage of IExpress (while updating IExpress’ user experience).  The following requirements are a rehash of some of IExpress’ capabilities):
    • The SEE contains a set of files as specified by the user
    • The SEE may include a license file to be displayed to the user before taking another action
    • The SEE may include a simple prompt to be displayed to the user before taking another action
    • The SEE may include an executable to be run after extraction
    • The SEE may include a second executable to be run after the one mentioned above
    • The SEE may control whether the system is rebooted after the executable is run
    • The SEE may control whether the user is shown any user interface whatsoever
    • The SEE may control whether feedback (via an animated dialog) during the unpacking of the contained files is displayed to the user
  • Create a patching tool delivered via a SEE that has the following capabilities:
    • Given a target directory (we will get to how the target directory is discovered in a minute):
      • Check the set of files included in the SEE to see if any files in the target directory are a match and update them
        • Check file version first if applicable
      • Optionally check the set of files included against files found in subdirectories of the target directory and update them
      • Optionally create a “file map” that allows for the placement of files in the target directory or subdirectories that may not exist (this allows for adding things to the target installation—in my case, I have “agents” that simply need to be dropped in a subdirectory to become active in the installation)
    • Provide for the discovery of the target directory through four mechanisms:
      • Prompt the user to choose the installation directory
      • Scan the machine for the files and replace them wherever they are found (this is useful because my assemblies’ names always match their enclosing namespace, such as “Mcs.Epm.Services.EpmExecutive.exe”
      • Scan the machine for a single file name. Once found, the location of the file becomes the target directory and update continues from there
      • Provide a mechanism for taking a “registry hint”, i.e. a registry value that represents the target directory
        • The registry value may contain a directory (for example “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\12.0\Project\InstallRoot\Path”
        • The registry value may contain a file name, which will be stripped away to arrive at the target directory
        • The registry hint may also allow for appending a subdirectory (for example HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\12.0\Project\InstallRoot\Path[MySubDirectory]”)
        • The registry hint may also allow for walking up the path one level  (for example HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\12.0\Project\InstallRoot\Path[…]”)
    • Includes a bootstrapper that ensures the .NET Framework is installed
      • If not, take the user to a link where it can be downloaded
      • If so, launch the patch component
  • Provide a user interface for creating, building, and managing patches.

Usage Scenarios

I can envision many ways this can be used, but I will give you a concrete real world example where this has already been used.  I wrote a Windows service that looks to an “agents” directory to periodically load and execute any assembly which implements the IAgent interface.  I pushed a full install to the customer’s environment.  The next day the engagement manager wanted a change to one of the agents’ behavior.  The change was so small that it didn't require a full reinstall so I used QuickPatch to deliver the change.  The client received an executable.  They ran it and the patch was complete.  I used a registry hint (the location of the Windows service) to figure out where the patch should be applied.

QuickPatch Design

There are four major components to QuickPatch:

  1. IExpress – The tool supplied by Microsoft for generating self-extracting executables and running setup programs.
  2. QuickPatch – The WinForms application I wrote for creating, building, and managing patches
  3. QuickPatchInstaller – The application I wrote for applying a patch
  4. QuickPatchBootStrapper – A small C++ program used to detect whether or not the .NET framework is installed before launching QuickPatchInstaller.  QuickPatch is not intended to be an installation tool.  It assumes that you are patching an existing .NET installation, so the framework should be present.  The bootstrapper is just a backstop to ensure the user experience is decent if the framework is not present.

Let’s take a look at 2-4.

The QuickPatch Application

Here is a screen shot of the application with a patch open for editing:

image

See my previous post for a detailed description of the “Package” tab.  Below is a screen shot of the same screen with the “Patch” tab displayed:

image

Note the Advanced section has a “file map” defined with several sub directories.

Let’s build the patch:

image

And run the patch:

image

Clicking the image  button changes the user interface to show the log of changes (and errors if necessary):

image

In the registry you can see the path used:

image

And in the file system you can see the results:

image

More next week.  Have a good weekend.

UPDATE: SlickEdit has some cool gadgets for Visual Studio.  Here is a LOC report:

image