在线更新的实现2

来源:互联网 发布:截取铃声的软件 编辑:程序博客网 时间:2024/05/01 00:30

 将 update.xml 放到服务器上后,通过一个程序读取,并获得更新文件的列表。进行版本比较后,对版本不同的文件进行更新。

 

  1. 更新程序的代码:
  2. unit frmMain;
  3. interface
  4. uses
  5.    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  6.    Dialogs, xmldom, XMLIntf, RzStatus, ExtCtrls, RzPanel, msxmldom, XMLDoc,
  7.    StdCtrls, CheckLst, IdBaseComponent, IdComponent, IdTCPConnection,
  8.    IdTCPClient, IdHTTP, StrUtils, DHibernateThread, DHibernateBase,
  9.    MD5Real, ActiveX, IdExplicitTLSClientServerBase, IdFTP, untUtils,
  10.    DHibernatePodoList, HTTPGet, ComCtrls, DHibernateSQLThread, ShellAPI,
  11.    WinSkinData, IniFiles;
  12. type
  13.    TDownFileRec = class
  14.    public
  15.      FName: string;
  16.      FSize: Integer;
  17.      FDir: string;
  18.      FCRC: string;
  19.      FTrueName: string;
  20.    end;
  21. type
  22.    TFormMain = class(TForm)
  23.      HTTPXML: TIdHTTP;
  24.      Label1: TLabel;
  25.      edtUpdateXml: TEdit;
  26.      Label2: TLabel;
  27.      lstFiles: TCheckListBox;
  28.      btnDownload: TButton;
  29.      XML: TXMLDocument;
  30.      RzStatusBar1: TRzStatusBar;
  31.      spStat: TRzStatusPane;
  32.      thrdSF: TDHibernateThread;
  33.      HTTPGet1: THTTPGet;
  34.      pb: TProgressBar;
  35.      SkinData1: TSkinData;
  36.      btnGetXml: TButton;
  37.      btnSetting: TButton;
  38.      spProc: TRzStatusPane;
  39.      chkSelAll: TCheckBox;
  40.      procedure btnGetXmlClick(Sender: TObject);
  41.      procedure FormCreate(Sender: TObject);
  42.      procedure btnDownloadClick(Sender: TObject);
  43.      procedure HTTPXMLStatus(ASender: TObject; const AStatus: TIdStatus;
  44.        const AStatusText: string);
  45.      // procedure DHibernateThread1Execute(Sender: TObject; params: IMap);
  46.      procedure HTTPXMLWork(ASender: TObject; AWorkMode: TWorkMode;
  47.        AWorkCount: Integer);
  48.      //     procedure DHibernateThread1Finish(Sender: TObject);
  49.      procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  50.      //     procedure SFFound(Sender: TObject; Path: string);
  51.      //     procedure SFEnded(Sender: TObject);
  52.      procedure thrdSFExecute(Sender: TObject; params: IMap);
  53.      procedure thrdSFbegin(Sender: TObject);
  54.      procedure thrdSFFinish(Sender: TObject);
  55.      procedure HTTPXMLWorkBegin(ASender: TObject; AWorkMode: TWorkMode;
  56.        AWorkCountMax: Integer);
  57.      procedure HTTPGet1Progress(Sender: TObject; TotalSize, Readed: Integer);
  58.      procedure HTTPGet1DoneFile(Sender: TObject; FileName: string;
  59.        FileSize: Integer);
  60.      procedure btnSettingClick(Sender: TObject);
  61.      procedure chkSelAllClick(Sender: TObject);
  62.      procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  63.    private
  64.      AbortTransfer: Boolean;
  65.      isUpdating: boolean;
  66.      downloadStr: string;
  67.    public
  68.      function GetFileSize(aFileName: string): integer;
  69.      procedure HttpDownLoad(aURL, aFile: string; bResume: Boolean);
  70.      procedure CmdStopService;
  71.      procedure CmdStopProcess;
  72.      procedure CmdFileOperation;
  73.      procedure CmdStartProcess;
  74.      procedure CmdStartService;
  75.      procedure CmdReboot;
  76.      procedure LoadFromIni;
  77.      procedure SaveToIni;
  78.    end;
  79. var
  80.    FormMain           : TFormMain;
  81.    FileCode           : string;
  82.    FileName           : string;
  83.    found              : integer;
  84.    FileList           : TPodoList;
  85.    commandList        : TStringList;
  86. implementation
  87. {$R *.dfm}
  88. function TFormMain.GetFileSize(aFileName: string): integer;
  89. var
  90.    sr                 : TSearchRec;
  91. begin
  92.    if FindFirst(aFileName, faAnyFile, sr) = 0 then
  93.      Result := sr.Size
  94.    else
  95.      Result := 0;
  96.    FindClose(sr);
  97. end;
  98. procedure TFormMain.HttpDownLoad(aURL, aFile: string; bResume: Boolean);
  99. var
  100.    tStream            : TFileStream;
  101. begin                                    //Http方式下载
  102.    if FileExists(aFile) then              //如果文件已经存在
  103.      tStream := TFileStream.Create(aFile, fmOpenWrite)
  104.    else
  105.      tStream := TFileStream.Create(aFile, fmCreate);
  106.    if bResume then                        //续传方式
  107.    begin
  108.      HTTPXML.Request.ContentRangeStart := tStream.Size - 1;
  109.      tStream.Position := tStream.Size - 1//移动到最后继续下载
  110.      HTTPXML.Head(aURL);
  111.      // HTTPXML.Request.ContentRangeEnd := HTTPXML.Response.ContentLength;
  112.    end
  113.    else                                   //覆盖或新建方式
  114.    begin
  115.      HTTPXML.Request.ContentRangeStart := 0;
  116.    end;
  117.    try
  118.      HTTPXML.Get(aURL, tStream);          //开始下载
  119.    finally
  120.      tStream.Free;
  121.    end;
  122. end;
  123. procedure TFormMain.btnDownloadClick(Sender: TObject);
  124. var
  125.    i                  : Integer;
  126.    furl               : string;
  127.    path               : string;
  128.    saveFile           : string;
  129. begin
  130.    if isUpdating then
  131.    begin
  132.      AbortTransfer := not AbortTransfer;
  133.      if AbortTransfer then
  134.      begin
  135.        // 暂停下载
  136.        HTTPGet1.Abort;
  137.        btnDownload.Caption := '续传';
  138.      end
  139.      else
  140.      begin
  141.        HTTPGet1.GetFile;
  142.        btnDownload.Caption := '暂停';
  143.        // DHibernateThread1Execute(Self, nil);
  144.      end;
  145.    end
  146.    else
  147.    begin
  148.      if lstFiles.Items.Count = 0 then
  149.        Exit;
  150.      // btnDownload.Enabled := false;
  151.      btnDownload.Caption := '暂停';
  152.      btnGetXml.Enabled := false;
  153.      btnSetting.Enabled := False;
  154.      lstFiles.Enabled := False;
  155.      isUpdating := True;
  156.      // 执行脚本
  157.      // stop service
  158.      CmdStopService;
  159.      // stop process
  160.      CmdStopProcess;
  161.      // download
  162.      path := edtUpdateXml.Text;
  163.      for i := 0 to lstFiles.Items.Count - 1 do
  164.      begin
  165.        if lstFiles.Checked[i] then
  166.        begin
  167.          furl := path + '/' + TDownFileRec(FileList.Objects[i]).FName;
  168.          saveFile := ExtractFilePath(ParamStr(0)) + '/' + TDownFileRec(FileList.Objects[i]).FDir + '/' +
  169.            TDownFileRec(FileList.Objects[i]).FTrueName;
  170.          if not FileExists(saveFile + '.ini'then
  171.            DeleteFile(saveFile);
  172.          downloadStr := '正在下载:' + lstFiles.Items[i];
  173.          HTTPGet1.FileName := saveFile;
  174.          HTTPGet1.URL := furl;
  175.          HTTPGet1.GetFile;
  176.        end;
  177.      end;
  178.      // file operation
  179.      CmdFileOperation;
  180.      // start process
  181.      CmdStartProcess;
  182.      // start service
  183.      CmdStartService;
  184.      // reboot?
  185.      CmdReboot;
  186.      isUpdating := false;
  187.      btnDownload.Caption := '下载并更新';
  188.      spStat.Caption := '下载完毕!';
  189.      spproc.Caption := EmptyStr;
  190.      btnGetXml.Enabled := True;
  191.      btnSetting.Enabled := True;
  192.      lstFiles.Enabled := True;
  193.      self.thrdSF.Execute(nil);
  194.      pb.Position := 0;
  195.    end;
  196. end;
  197. procedure TFormMain.btnGetXmlClick(Sender: TObject);
  198. begin
  199.    self.thrdSF.Execute(nil);
  200. end;
  201. procedure TFormMain.btnSettingClick(Sender: TObject);
  202. var
  203.    str                : string;
  204. begin
  205.    str := edtUpdateXml.Text;
  206.    str := InputBox('输入网址''输入更新服务器的所在地址:    ', str);
  207.    if str <> EmptyStr then
  208.      edtUpdateXml.Text := str;
  209. end;
  210. procedure TFormMain.chkSelAllClick(Sender: TObject);
  211. var
  212.    i                  : Integer;
  213. begin
  214.    for i := 0 to lstFiles.Items.Count - 1 do
  215.      lstFiles.Checked[i] := chkSelAll.Checked;
  216. end;
  217. procedure TFormMain.CmdFileOperation;
  218. var
  219.    i                  : Integer;
  220.    cmd                : string;
  221. begin
  222.    // todo: file operation
  223.    for i := 0 to commandList.Count - 1 do
  224.    begin
  225.      cmd := commandList[i];
  226.      if Pos('copy', cmd) > 0 then
  227.      begin
  228.        DoCopyUpdateFile(cmd);
  229.      end;
  230.      if Pos('rename', cmd) > 0 then
  231.      begin
  232.        DoRenameUpdateFile(cmd);
  233.      end;
  234.      if Pos('delete', cmd) > 0 then
  235.      begin
  236.        DoDeleteUpdateFile(cmd);
  237.      end;
  238.    end;
  239. end;
  240. procedure TFormMain.CmdReboot;
  241. var
  242.    i                  : Integer;
  243. begin
  244.    // todo: reboot
  245.    for i := 0 to commandList.Count - 1 do
  246.    begin
  247.      if commandList[i] = '/reboot' then
  248.      begin
  249.        rebootWindows;
  250.        Exit;
  251.      end;
  252.    end;
  253. end;
  254. procedure TFormMain.CmdStartProcess;
  255. var
  256.    i                  : Integer;
  257.    cmd                : string;
  258. begin
  259.    // todo: start process
  260.    for i := 0 to commandList.Count - 1 do
  261.    begin
  262.      Application.ProcessMessages;
  263.      // fmt: /run "process Name"
  264.      if Pos('run', commandList[i]) > 0 then
  265.      begin
  266.        cmd := commandList[i];
  267.        // 去掉 run
  268.        cmd := RightStr(cmd, Length(cmd) - 4);
  269.        cmd := StringReplace(cmd, '"', EmptyStr, [rfReplaceAll, rfIgnoreCase]);
  270.        cmd := Trim(cmd);
  271.        SetCurrentDir(ExtractFilePath(ParamStr(0)));
  272.        ShellExecute(0'open', PChar(ExtractFilePath(ParamStr(0)) + '/' + cmd), nil,
  273.          PChar(ExtractFilePath(ExtractFilePath(ParamStr(0)) + '/' + cmd)), SW_SHOW);
  274.      end;
  275.    end;
  276. end;
  277. procedure TFormMain.CmdStartService;
  278. var
  279.    i                  : Integer;
  280.    cmd                : string;
  281. begin
  282.    // todo: start service
  283.    for i := 0 to commandList.Count - 1 do
  284.    begin
  285.      Application.ProcessMessages;
  286.      // fmt: /start "service name"
  287.      if Pos('start', commandList[i]) > 0 then
  288.      begin
  289.        cmd := commandList[i];
  290.        // 去掉 /,添加 net
  291.        cmd := 'net ' + RightStr(cmd, Length(cmd) - 1);
  292.        cmd := StringReplace(cmd, '"', EmptyStr, [rfReplaceAll, rfIgnoreCase]);
  293.        ServicesOperation(cmd);
  294.      end;
  295.    end;
  296. end;
  297. procedure TFormMain.CmdStopProcess;
  298. var
  299.    i                  : Integer;
  300.    cmd                : string;
  301. begin
  302.    // todo: stop process
  303.    for i := 0 to commandList.Count - 1 do
  304.    begin
  305.      Application.ProcessMessages;
  306.      // fmt: /kill "process Name"
  307.      if Pos('kill', commandList[i]) > 0 then
  308.      begin
  309.        cmd := commandList[i];
  310.        // 去掉 kill
  311.        cmd := RightStr(cmd, Length(cmd) - 5);
  312.        cmd := StringReplace(cmd, '"', EmptyStr, [rfReplaceAll, rfIgnoreCase]);
  313.        cmd := Trim(cmd);
  314.        KillTask(cmd);
  315.      end;
  316.    end;
  317. end;
  318. procedure TFormMain.CmdStopService;
  319. var
  320.    i                  : Integer;
  321.    cmd                : string;
  322. begin
  323.    // todo: stop service
  324.    for i := 0 to commandList.Count - 1 do
  325.    begin
  326.      Application.ProcessMessages;
  327.      // fmt: /stop "service name"
  328.      if Pos('stop', commandList[i]) > 0 then
  329.      begin
  330.        cmd := commandList[i];
  331.        // 去掉 /,添加 net
  332.        cmd := 'net ' + RightStr(cmd, Length(cmd) - 1);
  333.        cmd := StringReplace(cmd, '"', EmptyStr, [rfReplaceAll, rfIgnoreCase]);
  334.        ServicesOperation(cmd);
  335.      end;
  336.    end;
  337. end;
  338. procedure TFormMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  339. begin
  340.    if isUpdating then
  341.    begin
  342.      //     MessageBox(Handle, '正在更新中,不能关闭!', '提示', MB_OK or
  343.      //       MB_ICONINFORMATION);
  344.      //     CanClose := False;
  345.      HTTPGet1.Abort;
  346.    end;
  347.    SaveToIni;
  348. end;
  349. procedure TFormMain.FormCreate(Sender: TObject);
  350. begin
  351.    LoadFromIni;
  352.    if edtUpdateXml.Text <> EmptyStr then
  353.      btnGetXmlClick(self);
  354.    isUpdating := False;
  355. end;
  356. procedure TFormMain.FormKeyDown(Sender: TObject; var Key: Word;
  357.    Shift: TShiftState);
  358. var
  359.    path               : string;
  360. begin
  361.    if Key = VK_F1 then
  362.    begin
  363.      path := ExtractFilePath(ParamStr(0)) + '/Help/';
  364.      ShellExecute(0'open', PChar(path + 'help_index.html'), nil, PChar(path), SW_SHOW);
  365.    end;
  366. end;
  367. procedure TFormMain.HTTPGet1DoneFile(Sender: TObject; FileName: string;
  368.    FileSize: Integer);
  369. var
  370.    iniName            : string;
  371. begin
  372.    ininame := HTTPGet1.FileName + '.ini';
  373.    DeleteFile(iniName);
  374.    isUpdating := false;
  375.    btnDownload.Caption := '下载并更新';
  376.    spStat.Caption := '下载完毕!';
  377.    spproc.Caption := EmptyStr;
  378.    btnGetXml.Enabled := True;
  379.    btnSetting.Enabled := True;
  380.    lstFiles.Enabled := True;
  381.    self.thrdSF.Execute(nil);
  382.    pb.Position := 0;
  383. end;
  384. procedure TFormMain.HTTPGet1Progress(Sender: TObject; TotalSize,
  385.    Readed: Integer);
  386. begin
  387.    Application.ProcessMessages;
  388.    spstat.Caption := downloadStr;
  389.    spProc.Caption := Format('%d / %d B', [Readed, TotalSize]);
  390.    pb.Max := TotalSize;
  391.    pb.Position := Readed;
  392. end;
  393. procedure TFormMain.HTTPXMLStatus(ASender: TObject; const AStatus: TIdStatus;
  394.    const AStatusText: string);
  395. begin
  396.    // spStat.Caption := Format(downloadStr,[AStatusText]);
  397. end;
  398. procedure TFormMain.HTTPXMLWork(ASender: TObject; AWorkMode: TWorkMode;
  399.    AWorkCount: Integer);
  400. begin
  401.    if AbortTransfer then
  402.    begin                                  //中断下载
  403.      HTTPXML.Disconnect;
  404.    end;
  405.    Application.ProcessMessages;
  406.    spStat.Caption := Format(downloadStr, [AWorkCount]);
  407. end;
  408. procedure TFormMain.HTTPXMLWorkBegin(ASender: TObject; AWorkMode: TWorkMode;
  409.    AWorkCountMax: Integer);
  410. begin
  411.    AbortTransfer := False;
  412. end;
  413. procedure TFormMain.LoadFromIni;
  414. var
  415.    iniName            : string;
  416.    ini                : TIniFile;
  417. begin
  418.    iniName := ExtractFilePath(ParamStr(0)) + 'update.ini';
  419.    ini := TIniFile.Create(iniName);
  420.    edtUpdateXml.Text := ini.ReadString('Server''Address', EmptyStr);
  421.    ini.Free;
  422. end;
  423. procedure TFormMain.SaveToIni;
  424. var
  425.    iniName            : string;
  426.    ini                : TIniFile;
  427. begin
  428.    iniName := ExtractFilePath(ParamStr(0)) + 'update.ini';
  429.    ini := TIniFile.Create(iniName);
  430.    ini.WriteString('Server''Address', edtUpdateXml.Text);
  431.    ini.Free;
  432. end;
  433. procedure TFormMain.thrdSFExecute(Sender: TObject; params: IMap);
  434. var
  435.    furl               : string;
  436.    xmlstr             : string;
  437.    node               : IXMLNode;
  438.    detail             : IXMLNode;
  439.    fileRec            : TDownFileRec;
  440.    fn                 : string;
  441.    // ms                 : TMemoryStream;
  442. begin
  443.    ActiveX.CoInitialize(nil);
  444.    furl := edtUpdateXml.Text + 'update.xml';
  445.    xmlstr := HTTPXML.Get(furl);
  446.    // ms.ReadBuffer(xmlstr, ms.Size);
  447.    // xmlstr := leftstr(xmlstr, Pos('-', xmlstr) - 1);
  448.    // ShowMessage(xmlstr);
  449.    XML.Active := false;
  450.    XML.XML.Text := xmlstr;
  451.    xml.Active := true;
  452.    node := XML.DocumentElement;
  453.    lstFiles.Items.Clear;
  454.    FileList.Clear;
  455.    if { 3 } node <> nil then
  456.    begin
  457.      node := XML.DocumentElement.ChildNodes.First;
  458.      while node <> nil do
  459.      begin
  460.        if { 2 } node.NodeName = 'file' then
  461.        begin
  462.          filerec := TDownFileRec.Create;
  463.          // name
  464.          detail := node.ChildNodes[0];
  465.          fileRec.FName := detail.NodeValue;
  466.          // size
  467.          detail := node.ChildNodes[1];
  468.          fileRec.FSize := detail.NodeValue;
  469.          // dir
  470.          detail := node.ChildNodes[2];
  471.          if detail.NodeValue = null then
  472.            fileRec.FDir := EmptyStr
  473.          else
  474.            fileRec.FDir := detail.NodeValue;
  475.          // crc
  476.          detail := node.ChildNodes[3];
  477.          fileRec.FCRC := detail.NodeValue;
  478.          // true name
  479.          detail := node.ChildNodes[4];
  480.          fileRec.FTrueName := detail.NodeValue;
  481.          // check whether need update
  482.          fn := ExtractFilePath(ParamStr(0)) + '/' + filerec.FDir + '/' + filerec.FTrueName;
  483.          if { 1 } MD5Real.RivestFile(fn) <> fileRec.FCRC then
  484.          begin
  485.            // add to list
  486.            FileList.Add(fileRec);
  487.            //         FileName := detail.NodeValue;
  488.            lstFiles.Items.Add(fileRec.FTrueName);
  489.          end;                             { if 1 }
  490.        end;                               { if 2 }
  491.        if node.NodeName = 'command' then
  492.        begin
  493.          if node.NodeValue <> null then
  494.            commandList.Add(node.NodeValue);
  495.        end;
  496.        // lstFiles.Items.Add(node.NodeValue);
  497.        node := node.NextSibling;
  498.      end;                                 { while }
  499.    end;
  500.    chkSelAllClick(self);                  { if 3 }
  501.    ActiveX.CoUninitialize;
  502. end;
  503. procedure TFormMain.thrdSFbegin(Sender: TObject);
  504. begin
  505.    spStat.Caption := '获取更新文件列表';
  506.    btnGetXml.Enabled := False;
  507.    btnDownload.Enabled := False;
  508.    lstFiles.Enabled := False;
  509. end;
  510. procedure TFormMain.thrdSFFinish(Sender: TObject);
  511. begin
  512.    btnGetXml.Enabled := True;
  513.    btnDownload.Enabled := True;
  514.    lstFiles.Enabled := True;
  515.    spStat.Caption := '准备就绪';
  516.    if lstFiles.Items.Count = 0 then
  517.    begin
  518.      btnDownload.Caption := '下载并更新';
  519.      btnDownload.Enabled := False;
  520.    end;
  521. end;
  522. initialization
  523.    FileList := TPodoList.Create;
  524.    commandList := TStringList.Create;
  525. finalization
  526.    FileList.Free;
  527.    commandList.Free;
  528. end.
  529. 更新的原理很简单,先执行 xml 中包含的脚本,然后下载文件,最后再执行脚本,完成整个更新。
  530. 用到的控件是 HttpGet,用它来进行断点续传。
  531. 程序截图:

 

原创粉丝点击