首先是要有个能放更新文件的服务器,把要更新的文件放上去。然后做一个 xml 文件,用于保存更新文件的信息。对于一个文件,是否需要更新,采用 md5 的方式去判断。如果 md5 值相同,则表示是同一个文件,不需要再更新。
xml 生成工具的代码:
- unit frmMain;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, xmldom, XMLIntf, Menus, StdCtrls, msxmldom, XMLDoc, OBDragDrop,
- ExtCtrls, MD5Real, ComCtrls, WinSkinData;
- type
- TFormMain = class(TForm)
- XML: TXMLDocument;
- PopupMenu1: TPopupMenu;
- N1: TMenuItem;
- N2: TMenuItem;
- N3: TMenuItem;
- N4: TMenuItem;
- N5: TMenuItem;
- N6: TMenuItem;
- N7: TMenuItem;
- N9: TMenuItem;
- MainMenu1: TMainMenu;
- F1: TMenuItem;
- XML1: TMenuItem;
- XML3: TMenuItem;
- N10: TMenuItem;
- N11: TMenuItem;
- N12: TMenuItem;
- N13: TMenuItem;
- N14: TMenuItem;
- N20: TMenuItem;
- H1: TMenuItem;
- OBDragDrop1: TOBDragDrop;
- odSelFile: TOpenDialog;
- N21: TMenuItem;
- N22: TMenuItem;
- N23: TMenuItem;
- Panel1: TPanel;
- Label1: TLabel;
- Splitter1: TSplitter;
- Panel2: TPanel;
- Label2: TLabel;
- mmCommands: TMemo;
- odOpenXml: TOpenDialog;
- sdSaveXml: TSaveDialog;
- lstUpdateFiles: TListView;
- pmDir: TPopupMenu;
- N15: TMenuItem;
- N16: TMenuItem;
- N17: TMenuItem;
- N18: TMenuItem;
- N8: TMenuItem;
- N19: TMenuItem;
- N24: TMenuItem;
- SkinData1: TSkinData;
- XML2: TMenuItem;
- procedure OBDragDrop1Drop(Sender: TObject; Pos: TPoint;
- Value: TStringList);
- procedure N14Click(Sender: TObject);
- procedure N9Click(Sender: TObject);
- procedure lstUpdateFilesDblClick(Sender: TObject);
- procedure N20Click(Sender: TObject);
- procedure N12Click(Sender: TObject);
- procedure XML1Click(Sender: TObject);
- procedure FormCreate(Sender: TObject);
- procedure XML2Click(Sender: TObject);
- procedure XML3Click(Sender: TObject);
- procedure N10Click(Sender: TObject);
- procedure N18Click(Sender: TObject);
- procedure N21Click(Sender: TObject);
- procedure N23Click(Sender: TObject);
- procedure N17Click(Sender: TObject);
- procedure N15Click(Sender: TObject);
- procedure N24Click(Sender: TObject);
- private
- FileName: string;
- public
- function GetFileSize(aFileName: string): integer;
- procedure GenerateFileList;
- procedure CopyFilesToUpdateDir(Files: TStrings);
- function ValidateCommands: Boolean;
- end;
- var
- FormMain : TFormMain;
- fileList : TStringList;
- DirList : TStringList;
- implementation
- {$R *.dfm}
- function TFormMain.GetFileSize(aFileName: string): integer;
- var
- sr : TSearchRec;
- begin
- if FindFirst(aFileName, faAnyFile, sr) = 0 then
- Result := sr.Size
- else
- Result := 0;
- FindClose(sr);
- end;
- procedure TFormMain.OBDragDrop1Drop(Sender: TObject; Pos: TPoint;
- Value: TStringList);
- var
- i : Integer;
- node : TListItem;
- begin
- for i := 0 to Value.Count - 1 do
- begin
- // if lstUpdateFiles.Items.Item[i].Caption = ExtractFileName(Value[i]) then
- // Continue;
- node := Self.lstUpdateFiles.Items.Add;
- node.Caption := ExtractFileName(Value[i]);
- node.SubItems.Add(IntToStr(GetFileSize(Value[i])));
- node.SubItems.Add(EmptyStr);
- node.SubItems.Add(ExtractFileName(Value[i]));
- end;
- GenerateFileList;
- CopyFilesToUpdateDir(Value);
- end;
- function TFormMain.ValidateCommands: Boolean;
- var
- i : Integer;
- n, t : Integer;
- begin
- // todo: validate commands
- t := 0;
- n := 0;
- for i := 0 to mmCommands.Lines.Count - 1 do
- begin
- if Pos('stop', mmCommands.Lines[i]) > 0 then
- n := 1;
- if Pos('kill', mmCommands.Lines[i]) > 0 then
- n := 2;
- if (Pos('copy', mmCommands.Lines[i]) > 0) or (Pos('delete', mmCommands.Lines[i]) > 0) or (Pos('rename', mmCommands.Lines[i]) > 0) then
- n := 3;
- if Pos('run', mmCommands.Lines[i]) > 0 then
- n := 4;
- if Pos('start', mmCommands.Lines[i]) > 0 then
- n := 5;
- if Pos('reboot', mmCommands.Lines[i]) > 0 then
- n := 6;
- if n < t then
- begin
- // 顺序出错
- Result := False;
- Exit;
- end;
- t := n;
- end;
- Result := True;
- end;
- procedure TFormMain.XML1Click(Sender: TObject);
- begin
- // DONE: new file
- self.XML.Active := False;
- self.XML.XML.Clear;
- lstUpdateFiles.Items.Clear;
- mmCommands.Lines.Clear;
- FileName := EmptyStr;
- fileList.Clear;
- DirList.Clear;
- end;
- procedure TFormMain.XML2Click(Sender: TObject);
- var
- node : IXMLNode;
- detail : IXMLNode;
- str : string;
- li : TListItem;
- begin
- // DONE: open xml
- if not odOpenXml.Execute() then
- Exit;
- // open
- FileName := odOpenXml.FileName;
- self.XML.Active := False;
- self.XML.XML.LoadFromFile(FileName);
- self.XML.Active := True;
- node := xml.DocumentElement;
- if node = nil then
- Exit;
- lstUpdateFiles.Items.Clear;
- node := node.ChildNodes.First;
- while node <> nil do
- begin
- str := node.NodeName;
- if str = 'file' then
- begin
- detail := node.ChildNodes[0]; // name
- li := lstUpdateFiles.Items.Add;
- li.Caption := detail.NodeValue;
- detail := node.ChildNodes[1]; // size
- li.SubItems.Add(detail.NodeValue);
- detail := node.ChildNodes[2]; // dir
- if detail.NodeValue = null then
- li.SubItems.Add(EmptyStr)
- else
- li.SubItems.Add(detail.NodeValue);
- detail := node.ChildNodes[4];
- li.SubItems.Add(detail.NodeValue);
- // detail := node.ChildNodes[2]; // md5
- end;
- // lstUpdateFiles.Items.Add(string(node.NodeValue));
- if str = 'command' then
- mmCommands.Lines.Add(string(node.NodeValue));
- node := node.NextSibling;
- end;
- GenerateFileList;
- end;
- procedure TFormMain.XML3Click(Sender: TObject);
- var
- node : IXMLNode;
- sub : IXMLNode;
- i : Integer;
- sl : TStringList;
- detail : IXMLNode;
- begin
- if not ValidateCommands then
- begin
- MessageBox(Handle, '控制指令顺序有误!不能保存!', '提示', MB_OK or MB_ICONINFORMATION);
- Exit;
- end;
- // DONE: save xml
- if FileName = EmptyStr then
- begin
- N10Click(Self);
- Exit;
- end;
- self.XML.Active := False;
- self.XML.XML.Clear;
- self.XML.Active := True;
- node := self.XML.CreateNode('root');
- self.XML.DocumentElement := node;
- node := XML.DocumentElement;
- for i := 0 to lstUpdateFiles.Items.Count - 1 do
- begin
- sub := node.AddChild('file');
- detail := sub.AddChild('name');
- detail.NodeValue := lstUpdateFiles.Items[i].Caption;
- detail := sub.AddChild('size');
- detail.NodeValue := lstUpdateFiles.Items[i].SubItems[0];
- detail := sub.AddChild('dir');
- try
- detail.NodeValue := lstUpdateFiles.Items[i].SubItems[1];
- except
- detail.NodeValue := EmptyStr;
- end;
- detail := sub.AddChild('crc');
- detail.NodeValue := MD5Real.RivestFile(fileList[i]);
- detail := sub.AddChild('truename');
- detail.NodeValue := lstUpdateFiles.Items[i].SubItems[2];
- end;
- for i := 0 to mmCommands.Lines.Count - 1 do
- begin
- sub := node.AddChild('command');
- sub.NodeValue := mmCommands.Lines[i];
- end;
- sl := TStringList.Create;
- sl.Text := FormatXMLData(xml.XML.Text);
- sl.SaveToFile(FileName);
- sl.Free;
- end;
- procedure TFormMain.N14Click(Sender: TObject);
- var
- i : Integer;
- node : TListItem;
- begin
- if not odSelFile.Execute then
- Exit;
- for i := 0 to odSelFile.Files.Count - 1 do
- begin
- node := lstUpdateFiles.Items.Add;
- node.Caption := ExtractFileName(odSelFile.Files[i]);
- node.SubItems.Add(IntToStr(GetFileSize(odSelFile.Files[i])));
- node.SubItems.Add(EmptyStr);
- node.SubItems.Add(ExtractFileName(odSelFile.Files[i]));
- end;
- GenerateFileList;
- CopyFilesToUpdateDir(odSelFile.Files);
- end;
- procedure TFormMain.N15Click(Sender: TObject);
- var
- str : string;
- begin
- if lstUpdateFiles.Items.Count = 0 then
- Exit;
- if lstUpdateFiles.ItemIndex = -1 then
- Exit;
- str := lstUpdateFiles.Items.Item[lstUpdateFiles.ItemIndex].SubItems[1];
- str := InputBox('输入目录', '输入文件更新到的目录: ', str);
- if str = EmptyStr then
- Exit;
- lstUpdateFiles.Items.Item[lstUpdateFiles.ItemIndex].SubItems[1] := str;
- end;
- procedure TFormMain.N17Click(Sender: TObject);
- begin
- // todo: delete item
- if lstUpdateFiles.Items.Count = 0 then
- Exit;
- if lstUpdateFiles.ItemIndex = -1 then
- Exit;
- lstUpdateFiles.Items.Delete(lstUpdateFiles.ItemIndex);
- end;
- procedure TFormMain.N18Click(Sender: TObject);
- begin
- // todo: auto command
- end;
- procedure TFormMain.N9Click(Sender: TObject);
- var
- str : string;
- str2 : string;
- begin
- //
- case TMenuItem(Sender).Tag of
- 1:
- begin
- // download
- str := InputBox('输入文件名', '输入要下载的文件名: ',
- EmptyStr);
- if str <> EmptyStr then
- mmCommands.Lines.Add(Format('/download "%s"', [str]));
- end;
- 2:
- begin
- // update
- str := InputBox('输入文件名', '输入要更新的文件名: ',
- EmptyStr);
- if str <> EmptyStr then
- mmCommands.Lines.Add(Format('/update "%s"', [str]));
- end;
- 3:
- begin
- // stop service
- str := InputBox('输入服务名', '输入要停止的服务名: ',
- EmptyStr);
- if str <> EmptyStr then
- mmCommands.Lines.Add(Format('/stop "%s"', [str]));
- end;
- 4:
- begin
- // start service
- str := InputBox('输入服务名', '输入要启动的服务名: ',
- EmptyStr);
- if str <> EmptyStr then
- mmCommands.Lines.Add(Format('/start "%s"', [str]));
- end;
- 5:
- begin
- // copy file
- str := InputBox('输入文件名', '输入原文件名: ',
- EmptyStr);
- str2 := InputBox('输入文件名', '输入新文件名: ', EmptyStr);
- if (str <> EmptyStr) and (str2 <> EmptyStr) then
- mmCommands.Lines.Add(Format('/copy "%s" to "%s"', [str, str2]));
- end;
- 6:
- begin
- // delete file
- str := InputBox('输入文件名', '输入要删除的文件名: ',
- EmptyStr);
- if str <> EmptyStr then
- mmCommands.Lines.Add(Format('/delete "%s"', [str]));
- end;
- 7:
- begin
- // rename file
- str := InputBox('输入文件名', '输入原文件名: ',
- EmptyStr);
- str2 := InputBox('输入文件名', '输入新文件名: ', EmptyStr);
- if (str <> EmptyStr) and (str2 <> EmptyStr) then
- mmCommands.Lines.Add(Format('/rename "%s" to "%s"', [str, str2]));
- end;
- 8:
- begin
- // reboot software
- str := InputBox('输入程序名', '输入要重启的程序名: ',
- EmptyStr);
- if str <> EmptyStr then
- mmCommands.Lines.Add(Format('/restart "%s"', [str]));
- end;
- 9:
- begin
- // reboot computer
- mmCommands.Lines.Add('/reboot');
- end;
- 10:
- begin
- str := InputBox('输入进程名', '输入要停止的进程名称: ', EmptyStr);
- if str > EmptyStr then
- mmCommands.lines.Add(Format('/kill "%s"', [str]));
- end;
- 11:
- begin
- str := InputBox('输入进程名', '输入要开始的进程名称: ', EmptyStr);
- if str > EmptyStr then
- mmCommands.lines.Add(Format('/run "%s"', [str]));
- end;
- end;
- end;
- procedure TFormMain.FormCreate(Sender: TObject);
- begin
- FileName := EmptyStr;
- end;
- procedure TFormMain.lstUpdateFilesDblClick(Sender: TObject);
- begin
- if lstUpdateFiles.Items.Count = 0 then
- Exit;
- if lstUpdateFiles.ItemIndex = -1 then
- Exit;
- lstUpdateFiles.Items.Delete(lstUpdateFiles.ItemIndex);
- end;
- procedure TFormMain.N20Click(Sender: TObject);
- begin
- if MessageBox(Handle, '确定要删除所有的更新文件吗?', '提示', MB_YESNO or
- MB_ICONINFORMATION) = idno then
- Exit;
- lstUpdateFiles.Items.Clear;
- end;
- procedure TFormMain.N21Click(Sender: TObject);
- begin
- // todo: help
- end;
- procedure TFormMain.N23Click(Sender: TObject);
- begin
- // todo : about
- end;
- procedure TFormMain.N24Click(Sender: TObject);
- var
- str : string;
- begin
- if lstUpdateFiles.Items.Count = 0 then
- Exit;
- if lstUpdateFiles.ItemIndex = -1 then
- Exit;
- str := lstUpdateFiles.Items.Item[lstUpdateFiles.ItemIndex].SubItems[2];
- str := InputBox('输入文件名', '输入文件的真实文件名: ', str);
- if str = EmptyStr then
- Exit;
- lstUpdateFiles.Items.Item[lstUpdateFiles.ItemIndex].SubItems[2] := str;
- end;
- procedure TFormMain.N10Click(Sender: TObject);
- var
- sl : TStringList;
- i : Integer;
- node : IXMLNode;
- sub : IXMLNode;
- detail : IXMLNode;
- begin
- if not ValidateCommands then
- begin
- MessageBox(Handle, '控制指令顺序有误!不能保存!', '提示', MB_OK or MB_ICONINFORMATION);
- Exit;
- end;
- // DONE: save as ...
- if not sdSaveXml.Execute() then
- Exit;
- FileName := sdSaveXml.FileName;
- self.XML.Active := False;
- self.XML.XML.Clear;
- self.XML.Active := True;
- node := self.XML.CreateNode('root');
- self.XML.DocumentElement := node;
- node := XML.DocumentElement;
- for i := 0 to lstUpdateFiles.Items.Count - 1 do
- begin
- sub := node.AddChild('file');
- detail := sub.AddChild('name');
- detail.NodeValue := lstUpdateFiles.Items[i].Caption;
- detail := sub.AddChild('size');
- detail.NodeValue := lstUpdateFiles.Items[i].SubItems[0];
- detail := sub.AddChild('dir');
- try
- detail.NodeValue := lstUpdateFiles.Items[i].SubItems[1];
- except
- detail.NodeValue := EmptyStr;
- end;
- detail := sub.AddChild('crc');
- detail.NodeValue := MD5Real.RivestFile(fileList[i]);
- detail := sub.AddChild('truename');
- detail.NodeValue := lstUpdateFiles.Items[i].SubItems[2];
- end;
- for i := 0 to mmCommands.Lines.Count - 1 do
- begin
- sub := node.AddChild('command');
- sub.NodeValue := mmCommands.Lines[i];
- end;
- sl := TStringList.Create;
- sl.Text := FormatXMLData(xml.XML.Text);
- sl.SaveToFile(FileName);
- sl.Free;
- end;
- procedure TFormMain.N12Click(Sender: TObject);
- begin
- Close;
- end;
- procedure TFormMain.GenerateFileList;
- var
- i : Integer;
- begin
- fileList.Clear;
- for i := 0 to lstUpdateFiles.Items.Count - 1 do
- begin
- fileList.Add(ExtractFilePath(ParamStr(0)) + '/Files/' +
- lstUpdateFiles.Items[i].Caption);
- end;
- end;
- procedure TFormMain.CopyFilesToUpdateDir(Files: TStrings);
- var
- i : Integer;
- begin
- //
- for i := 0 to Files.Count - 1 do
- begin
- CopyFile(PChar(Files[i]), PChar(ExtractFilePath(ParamStr(0)) + '/Files/' +
- ExtractFileName(Files[i])), False);
- end;
- end;
- initialization
- fileList := TStringList.Create;
- DirList := TStringList.Create;
- finalization
- fileList.Free;
- DirList.Free;
- end.
生成完的 xml 命名为 update.xml,放到服务器上,与更新文件放在一起。
其实看到上面的代码也就明白了,这个更新可以选择执行指令,比如说要更新某个服务,必须先停止服务再更新,或是先终止某个程序再更新。更新完毕后,可以再次启动程序或服务。