在软件开发过程中,经常需要对软件进行更新和维护。为了实现这一目标,可以使用补丁(Patch)来更新软件。补丁可以修复软件中的错误,改进功能,或者添加新的特性。本文将介绍如何在Delphi中使用Microsoft PatchAPI接口来创建和应用补丁,以及如何实现补丁的回滚功能。
一直想要创建自己的安装包和补丁。认为每个人都有这样的想法。总是认为这是一个神奇的过程,需要使用预先构建的安装程序来构建它们。本文不会教如何创建一个完整的应用程序安装程序构建器,但它将给一些关于如何创建旧版本和新版本文件之间的补丁的见解。
本文的代码比以前的文章更高级,但如果有开发背景,应该能理解它。将注意到源代码附带了两个DLL文件,分别是mspatcha.dll和mspatchc.dll。不需要这些DLL文件,但为了方便起见添加了它们。前者涉及应用补丁,后者涉及创建补丁(稍后会有更多内容)。首先,来看PatchAPI。
这个文件包含了原始DLL文件实际允许做什么的主要定义。它定义了所有常量、函数和实际的DLL调用定义到提到的DLL。有关PatchAPI的更多信息,请继续阅读。
这是生成的包装类,目的是减轻生成补丁文件和应用补丁的负担。它包含Delphi特定的设置值、自定义事件,甚至自定义异常类。已经尽可能多地注释了这个单元,所以如果有人需要更多关于正在发生的事情的解释,请告诉,将乐意帮助。
这显然是应用程序的主屏幕。它允许添加/编辑/删除想要补丁的文件,以及创建/应用补丁。
想要使用的主要对象是TPatcher类。它提供了创建和应用补丁文件的最简单和最有效的方法,而不需要使用PatchAPI类。创建了四个(自定义)事件,它们的作用如下:
:在创建或应用补丁时显示进度
:补丁创建或应用完成时发生
:文件正在被补丁或创建时发生
:文件补丁或创建结束时发生
不用担心,即使没有实现这些事件,补丁程序也会正常工作。实际上,补丁程序在没有添加任何东西的情况下也会运行得很好。为了方便起见,已经实现了所有四个自定义事件,这样就可以自己定义它们。理论上,如果创建一个文件的补丁,补丁实际上可以双向进行。如果没错的话,使用本文,可以通过合适的方式应用增量,使文件既可以是旧版本也可以是新版本。这就是(认为)任何安装应用程序在应用和回滚补丁方面的工作原理。
下面是一个自定义事件的定义和实现示例:
procedure TPatcherDemo.DoPatcherProgress(ASender: TObject; const ACurrentPosition: LongWord; const AMaximumPosition: LongWord; var ACanContinue: LongBool);
var
LStr: string;
begin
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);
mmo1.Lines.Add(LStr);
Application.ProcessMessages;
end;
当逐步执行程序时,会看到每次创建或应用补丁时都会触发它。
引入了常量类型数组的概念。基本上,根据类型定义,可以基于定义的类型创建一个常量数组。因此,基于类型定义创建了字符串定义,如下所示:
type
TPatchApplyOption = (
paoFailIfExact,
paoFailIfClose,
paoTestOnly,
paoValidFlags
);
TPatchApplyOptions = set of TPatchApplyOption;
const
Descriptions_TPatchApplyOption: array[Low(TPatchApplyOption)..High(TPatchApplyOption)] of string = (
'If the source file and the target are the same, return a failure and don''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''t create the target.',
'Don''t create the target.',
'The logical OR of all valid patch apply flags.'
);
在演示应用程序中,将看到这实际上是如何工作的,但会很快发现在哪里使用它。