delphi 快速制作通用LiveUpdate升级程序

很多朋友开发好程序,又需要时间去开发升级模块,比较麻烦,我在这里给出一个通用升级工具的解决方法。

首先,我们考虑下对这个升级程序或模块的要求,主要是通用性和便捷性这两点;在这里,我忽然想到了网络游戏的更新程序,发现它非常不错,我们可以像它一样,由主程序调用独立的LiveUpdate程序,对自己进行升级,这样就解决了通用性的问题,具体如何做呢?我们可以利用EXE文件参数的方法来实现,也就是给程序添加运行参数。

功能描述:通过参数和配置文件的形式,实现文件更新,采用HTTP协议,可方便的集成到软件中或用于文件升级。

缺点描述:配置时需要手工设置,不是断点续传,单线程。

特别说明:程序会自动开户下载任务,没有设置自动关闭的,可在下载后手工再点更新键下载一次。

参数描述:LiveUpdate 配置文件地址 是否自动关闭 需要执行的文件(只支持一个文件)

具体例子:

自动下载、关闭、启动|LiveUpdate http://localhost/outcall/liveupdate.ini 1 c:\smallarmy.exe
自动下载、关闭|LiveUpdate http://localhost/outcall/liveupdate.ini 1
自动下载|LiveUpdate http://localhost/outcall/liveupdate.ini

配置文件:注意FileTime这个项目,必须是yyyy-MM-dd hh:mm:ss,升级时只比较到秒的十位,个位不比较。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

[Update]

;需要更新的文件数 后面需要配套

Count=2

;文件名

File1=picturepartner.rar

;下载地址

FileUrl1=http://esin.onlinedown.net/down/picturepartner.rar

;覆盖路径

FilePath1=$AppPath

;文件版本号

FileVer1=88.88.88.8888

;更新时间,升级以这个为准,时间由您设置,升级后会强制更新文件的时间为以下时间

FileTime1=2010-10-21 12:12:33

File2=Smallarmy.exe

FileUrl2=http://sq.onlinedown.net/down/Smallarmy.exe

FilePath2=$AppPath

FileVer2=1.0.0.0

FileTime2=2010-10-11 12:12:33

LiveUpdate开发过程:

    首先找一些图片和图标资源,主要是与下载有关的即可;然后在Delphi中新建一个工程,在窗口上添加一个ListView用来显示下载项,两个ProgressBar用来显示总进度和下载项进度;由于考虑的是http方式,这个方式也比较方便,只需找个web空间就行,所以,在Delphi中,我们采用自带的indy组件包中的idHttp组件;在窗口中添加IdHttp和IdAntiFreeze各一个;IdHttp组件,用到两个事项,分别是WorkBegin和Work,主要是处理进程条的显示,代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

procedure TfrmMain.IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode;

  AWorkCount: Int64);

begin

  ProgressBar1.Position := ProgressBar1.Position + AWorkCount;

  Application.ProcessMessages;

end;

procedure TfrmMain.IdHTTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode;

  AWorkCountMax: Int64);

begin

  ProgressBar1.Max := AWorkCountMax;

  ProgressBar1.Min :=0;

  ProgressBar1.Position :=0;

end;

在listview上,我们添加几列内容,分别是图标列、文件、版本、日期、地址、路径,分别调整下宽度,后面地址和路径两列宽度为0,进行隐藏,这是用来保存下载项的放置目标地址和下载地址的;接下去我贴上主要的处理代码:

格式化文件修改日期的函数:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

type

  TFileTimeType = (fttCreation, fttLastAccess, fttLastWrite);

function SetFileDateTime(const FileName: string; FileTimeType: TFileTimeType;

  DateTime: TDateTime): integer;

var

  Handle: THandle;

  LocalFileTime, FileTime: TFileTime;

  DosDateTime: integer;

  I: TFileTimeType;

  FileTimes: array [TFileTimeType] of Pointer;

begin

  Result := 0;

  DosDateTime := DateTimeToFileDate(DateTime);

  Handle := FileOpen(FileName, fmOpenWrite or fmShareDenyNone);

  if Handle <> INVALID_HANDLE_VALUE then

    try

      for I := fttCreation to fttLastWrite do

        FileTimes[I] := nil;

      DosDateTimeToFileTime(LongRec(DosDateTime).Hi, LongRec(DosDateTime).Lo,

        LocalFileTime);

      LocalFileTimeToFileTime(LocalFileTime, FileTime);

      FileTimes[FileTimeType] := @FileTime;

      if SetFileTime(Handle, FileTimes[fttCreation], FileTimes[fttLastAccess],

        FileTimes[fttLastWrite]) then

        Exit;

    finally

      FileClose(Handle);

    end;

  Result := GetLastError;

end;

下载处理代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

procedure TfrmMain.BitBtn1Click(Sender: TObject);

var

  vStream: TMemoryStream;

  vIni: TIniFile;

  vSF, vS: string;

  I, vI: integer;

  vList: TListItem;

  vDown: Boolean;

begin

  BitBtn1.Enabled := False;

  IdAntiFreeze1.OnlyWhenIdle := False; // 设置使程序有反应.

  vSF := ParamStr(1); // 第一个参数必须是配置文件的地址

  vStream := TMemoryStream.Create;

  try

    try

      IdHTTP1.Get(vSF, vStream); // 取升级配置,由参数传进

    except

      Application.MessageBox('网络错误!无法获取升级配置文件。', '', MB_OK +

        MB_ICONSTOP);

      Exit;

    end;

    vSF := ExtractFilePath(ParamStr(0)) + 'LiveUpdate.ini';

    vStream.SaveToFile(vSF);

    vIni := TIniFile.Create(vSF);

    try

      vI := vIni.ReadInteger('Update', 'Count', 0);

      if vI = 0 then

      begin

        Application.MessageBox('没有可升级的文件!', '', MB_OK +

          MB_ICONINFORMATION);

        Application.Terminate;

        Exit;

      end;

      ListView1.Clear;

      for I := 1 to vI do

      begin

        vList := ListView1.Items.Add;

        vList.ImageIndex := 0;

        vList.SubItems.Add(vIni.ReadString('Update', 'File' + inttostr(I), ''));

        vList.SubItems.Add(

          vIni.ReadString('Update', 'FileVer' + inttostr(I), ''));

        vList.SubItems.Add(

          vIni.ReadString('Update', 'FileTime' + inttostr(I), ''));

        vList.SubItems.Add(

          vIni.ReadString('Update', 'FileUrl' + inttostr(I), ''));

        vS := vIni.ReadString('Update', 'FilePath' + inttostr(I), '');

        if StrUtils.ContainsText(vS, '$AppPath') then

          vS := StringReplace(vS, '$AppPath', ExtractFilePath(ParamStr(0)),

            [rfReplaceAll]); // 其实,用相对路径的方式也能实现一样的效果

        vList.SubItems.Add(vS);

      end;

      ProgressBar1.Position := 0;

      ProgressBar2.Position := 0;

      ProgressBar2.Max := ListView1.Items.Count;

      for I := 0 to ListView1.Items.Count - 1 do

      begin

        vStream.Clear;

        try

          vS := ListView1.Items.Item[I].SubItems.Strings[4]

            + ListView1.Items.Item[I].SubItems.Strings[0];

          if fileexists(vS) then // 如果文件存在,则进行校验

          begin // 只比较到秒的十位,秒的个位不比较

            vDown := Copy(FormatDateTime('yyyy-MM-dd hh:mm:ss',

              FileDateToDateTime(FileAge(vS))), 1, 18)

              <> Copy(ListView1.Items.Item[I].SubItems.Strings[2], 1, 18);

          end

          else

            vDown := True;

          if vDown then

          begin

            ListView1.Items.Item[I].ImageIndex := 3;

            IdHTTP1.Get(ListView1.Items.Item[I].SubItems.Strings[3], vStream);

            ListView1.Items.Item[I].ImageIndex := 4;

            Application.ProcessMessages;

            vStream.SaveToFile(vS);

            SetFileDateTime(vS, fttLastWrite,

              StrToDateTime(ListView1.Items.Item[I].SubItems.Strings[2]));

          end;

          ListView1.Items.Item[I].ImageIndex := 1;

        except // INDY控件一般要使用这种try..except结构.

          ListView1.Items.Item[I].ImageIndex := 2;

        end;

        ProgressBar2.Position := I + 1;

        vEnd := True;

      end;

    finally

      FreeAndNil(vIni);

    end;

  finally

    vStream.Free;

    BitBtn1.Enabled := True;

    DeleteFile(vSF);

  end;

end;

其他关于界面美化什么的,不再描述。完成后,就可以直接在各个项目中引用它,而无需每个项目都去开发升级程序或模块了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值