AppLife Update’s custom action infrastructure provides the ability for a publisher
to customize the activity during their application updates. An Update Action consists
of:
- An Update Action class. This is a class that
extends AppLife UpdateAction base class. In this class you can write your
own code to be executed as the update engine is running on your deployed clients.
- An Action Builder class. This is an optional
class that allows you perform custom activity as updates are built.
- An Update Action Editor. This is an optional user control that allows
you to create a user interface for an update publisher to configure the update action.
The default editor is a property grid that exposes any public property of the Update
Action class.

To create a custom action that utilizes the Delta Compression API, the action will
need to apply a patch file to the original file as the update is executed on the
client. This work is performed in the Update Action class Execute method.
Of course, to apply a patch, we will have first had to create the patch file. Patch
creation is performed in the Update Action Builder class PrepareForBuild
method. And finally, to make it easy and intuitive for a publisher to utilize this
custom action, a customized editor allows us to expose a user interface to easily
configure the action at build time, while hiding the non-config data carrier properties
of the action.
At a minimum, a custom action class must extend the core UpdateAction class
and override the Execute and Rollback methods. These methods correspond
to specific stages of the AppLife Update engine execution process. During the Execute
stage the update work is performed. If for any reason the update does not complete,
the process is rolled back and each action that has been executed undoes what the
Execute stage performed in the Rollback method.
To create the Patch File action, we create a .Net Class Library assembly(dll). After
adding a reference to the Kjs.AppLife.Update.Engine.Core.dll, a public class that
extends the UpdateAction class that includes a parameter-less constructor
is added. We then override the Execute method and add code that will apply
a patch to an existing file. In order to accomplish this, the action must know where
the base file is located on the client system and where to find the patch file.
This information is provided through the use of public properties. AppLife Update
automatically serializes Action public property information during the build process.
Public properties are populated by the Update Engine and are available to the action
at execution time. The publisher identifies the base file location on the client
by setting the TargetClientFolder and TargetClientSubpath properties.
There are BaseFile and TargetFile properties to identify the location
of these files on the build system. There is also a property that includes an MD5
hash of the target file which allows the action to verify the reconstructed target
file after the patch is applied. Lastly, an IsPatched property which identifies
whether the created patch file was larger than the target file. In this event the
IsPatched property is false and the update package includes the full un-patched
target file. The action uses this property to identify when to apply the patch.
The action uses an MSPatchWrapper class that encapsulates the Delta Compression
API. This is a non-managed API and the native P/Invoke methods are placed in a
NativeMethods class for distinct separation between managed and native code.
This differencing algorithm could be replaced with another by switching out the
functionality in the MSPatchWrapper class.
To implement this patching functionality, we must be able to create the update patch
and add this patch to the update package as an update is built. To perform this
work, we create a custom Action Builder. This is a class that extends the AppLife
ActionBuilder class and allows us to perform work as an update is being built.
The patch is created within the PrepareForBuild method. This method is executed
as AppLife Make Update builds the update package.
To assign a custom builder to an action, an attribute is added to the update action
class.
[ActionBuilder("AppLifeUpdateFilePatchingBuilder.PatchFileActionBuilder,
AppLifeUpdateFilePatchingBuilder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6f85fbced78dd5a2")]
public class PatchFileAction
: UpdateAction {...}
Note: An action builder can be placed in the same physical assembly as the action
itself. This project splits the action itself from the builder/editor in order to
maintain the smallest possible update package size. When an update package is built,
the assembly that contains the custom action is added to the update, but builder
and editor assemblies are not.
Now that the action knows about the builder, the action(and it’s properties) are
accessed from the builder through the base class Action property. For convenience,
a strongly typed new Action property is added that casts the Update Action as a
PatchFileAction class.
As we did with applying the patch, creating the patch is encapsulated into its own
class. This class utilizes the mspatchc.dll API to create the patch. Because
creating patches on larger files can take some time, a progress callback is implemented
to add progress indication to the build process. As previously mentioned, the builder
also creates an MD5 hash of the target file and adds this hash information to the
update package so that the reconstructed file can be verified.
Writing to the Build Log
Through the BuildContext object, we can write to the build log as the action
builder performs its work. The progress is written to the build log as well as the
final compression percentage.
Another function of an action builder class is to provide for validation of the
update action. By overriding the ValidateActionCore method, we can implement
validation logic and prevent AppLife Update from attempting to build an update if
the action configuration is not valid. At a minimum, the Base File and Target File
must be configured to create a patch, so these properties are verified. In addition,
unlike the apply patch API that the update engine uses to apply a patch, the patch
creation API does not ship with Windows. The Windows Platform SDK is required to
create a patch, so within the validation logic we look for the presence of this
API and invalidate the action if the SDK is not present.
To provide the update author an intuitive user interface, a custom action editor
is created. An action editor is simply a Windows Forms User Control. For the Patch
File action editor, we expose the ability to set a base file and a target file.
These are locations on the build machine where the two files exist. In addition,
the base file must be present on the target system and the update author can define
where on the target system the action will find the base file.
An action editor is launched by overriding the StartEditingAction method
of the Action Builder class.
The AppLife Update custom action functionality provides a great deal of extensibility
to the update capabilities of an AppLife Update enabled application. Using a custom
action, application-centric updating logic can be created and encapsulated into
configurable update actions that integrate into an update just like any of the built-in
update actions.
The custom patching action presented in this lab provides deployable patching functionality
that can be used to minimize update package size. The source code provided in the
accompanying download provides an example of how to create a custom action, action
builder, and editor. The patching can also be extended to operate on file sets or
utilize a different patching algorithm. All of the base classes are thoroughly documented
in the AppLife Update API Reference help.
For answers to questions about this example, please contact Kinetic Jump tech support.
techsupport@kineticjump.com
Download AppLife Update Here