We've all seen it before: applications updating software and allowing you to 'rollback' your changes. This article will show you how this can be accomplished in Delphi
using the Microsoft PatchAPI interface. The main object (discussed later) should work straight off the bat without you needing to add in anything with regards to the patching options.
I've always wanted to create my own installation packages and all that stuff. I think everyone has. I always thought it was this magical thing that just
'happened' and you had to use pre-built installation programs that you need to install in order to build them. This article does not show you how to make
a full fledged application installer builder, but it will give you insight into it with regards to creating patches between your old and new file versions.
This article will also show you how to use DLL files as well.
Unlike my previous articles, I am not going to show very much code, because I commented the source code quite well (I think).
So what's going on in the code?
This article is a lot more higher level than my earlier articles, but if you have a background in development, you should get the gist of it :).
You will notice that there will be two DLLs accompanying the source code, namely mspatcha.dll and mspatchc.dll. You shouldn't need any of these DLLs
but I added them for convenience's sake. The former concerns applying the patches while the latter involves creating the patches (more on that later). First things first:
This file contains the main definition for what the original DLL files actually allow you to do. It defines all the constants, functions, and the
actual DLL call definitions to the mentioned DLLs. For more information regarding PatchAPI, please read further here.
This is the wrapper class which I generated in order to take away the strain of generating the patch files and applying said patches. It contains Delphi specific set values,
custom events, and even a custom exception class. I did my best to comment as much as I could with this unit, so if anyone would like any other explanations with regard
to what is happening, please let me know and I will be happy to assist.
This obviously is the main screen of the application. It allows you to add/edit/remove files you want to patch as well as creating/applying patches.
Using the code
The object that you want to use mostly is the
TPatcher class. It provides the easiest and most effective way of creating and applying your patch files without
needing to work with the
PatchAPI class. There are four (custom) events which I created which do the following:
TOnPatchProgress: Shows you the progress when you create or apply a patch
TOnPatchComplete: Occurs when the patch create or apply is complete
TOnPatchFileBegin: Occurs when a file is being patched or created
TOnPatchFileEnd: Occurs when the end of a file patch or create is complete
Don't worry, the patcher will work fine if you do not implement these events :). In fact, the patcher will work quite fine without you adding in anything
more than just patch files that you have added. For your convenience, I have ensured that I implemented all four of the custom events so you can device your
own definitions for them. Theoretically, if you create a patch of a file, the patch can actually go both ways. If I am not mistaken, using this article,
you can make a file both the old and the new version just by applying the delta the way you see fit. This is how (I think) any installation application
works with regards to applying and rolling back a patch.
As a point of interest, I will demonstrate how one of the custom events are defined and implemented:
TOnPatchProgress = procedure(
ASender : TObject;
const ACurrentPosition : LongWord;
const AMaximumPosition : LongWord;
var ACanContinue : LongBool) of object;
This is the definition for the progress of the creating or patching of a file (obviously). So all you will need to do is create a corresponding definition
for the event like this (based on my demo application):
procedure TPatcherDemo.DoPatcherProgress(ASender : TObject;
const ACurrentPosition : LongWord;
const AMaximumPosition : LongWord;
var ACanContinue : LongBool);
LStr : string;
if AMaximumPosition <> ProgressBar1.Max then
ProgressBar1.Max := AMaximumPosition;
if ACurrentPosition <> ProgressBar1.Position then
ProgressBar1.Position := ACurrentPosition;
LStr := 'Complete: ' + FormatFloat('#,##0', ACurrentPosition) +
' of ' + FormatFloat('#,##0', AMaximumPosition);
When you step through the program, you will see that it fires each time something happens when the patch is created/applied.
I also introduce the concept of constant type arrays. All that basically means is that based on a type definition, you can create
a constant array based on the type that you defined. So based on that, I create string definitions based on the type definitions like this:
TPatchApplyOption = (
paoFailIfExact, // = APPLY_OPTION_FAIL_IF_EXACT
paoFailIfClose, // = APPLY_OPTION_FAIL_IF_CLOSE
paoTestOnly, // = APPLY_OPTION_TEST_ONLY
paoValidFlags // = APPLY_OPTION_VALID_FLAGS
TPatchApplyOptions = set of TPatchApplyOption;
Descriptions_TPatchApplyOption : array[Low(TPatchApplyOption)..High(TPatchApplyOption)] of string = (
'If the source file and the target are the same, return a failure and don'#39't create the target.',
'If the source file and the target differ by only rebase and bind
information (that is, they have the same normalized signature),
return a failure and don'#39't create the target.',
'Don'#39't create the target.',
'The logical OR of all valid patch apply flags.'
You will see in the demo application how this actually works, but you will find out quick enough where I use it :).
This object also allows you to use different kinds of input options but I only used ANSI (mostly) and Unicode (sometimes).
The other option is by handle, which I never tested. So if you feel that you want to use it and find issues, please let me know.
Points of interest
I had a bit of trouble with regards to inserting multiple files into a single patch file. The patcher also allows you to use symbol files
and anything that Windows has at its disposal. I just haven't had the chance to implement it all. If anyone wants me to add more functionality to this,
please let me know and I will be happy to update this article.
Microsoft (currently) uses two forms of patching interfaces, PatchAPI and MSDelta. The former being from XP down and the latter being from
Vista upwards. An issue which I found is, if you read the article regarding patching which I linked at the top of the article, PatchAPI works
quite nicely in Delphi 7 (I haven't tried it with the later ones), but MSDelta works quite fine with CBuilder, but apparently they are not interchangeable.
I will be posting my CBuilder article regarding MSDelta soon, so keep checking :). If anyone can make suggestions regarding building them into either or both, please let me know.