关键技术是获取版本号功能和批处理删除自身的功能
unit UnitUpG;
interface
uses
Forms,
Windows,
SysUtils,
Classes,
Controls,
URLMON,
SHellAPi,
iniFiles,
Tlhelp32;
procedure UpGrade;
procedure KillExe;
var
SName:String;
UpGradeB:Boolean;
type
TLANGANDCODEPAGE=record
wLanguage,wCodePage:Word;
end;
PLANGANDCODEPAGE=^TLANGANDCODEPAGE;
type
TUpDateThread=class(TThread)
protected
procedure Execute;override;
end;
implementation
uses UNIT1;
function ShowVersion:String;
var
VerInfo:PChar;
lpTranslate:PLANGANDCODEPAGE;
FileName:String;
VerInfoSize,cbTranslate:DWORD;
VerValueSize:DWORD;
Data:String;
VerFileV:PChar;
lpFileVersion:string;
begin
Result:='0.0.0.0';
FileName:=Application.ExeName;
VerInfoSize:=GetFileVersionInfoSize(PChar(FileName),VerInfoSize);
if VerInfoSize>0 then
begin
VerInfo:=AllocMem(VerInfoSize);
GetFileVersionInfo(PChar(FileName),0,VerInfoSize,VerInfo);
VerQueryValue(VerInfo, PChar('\VarFileInfo\Translation'), Pointer(lpTranslate),cbTranslate);
if cbTranslate<>0 then
begin
Data := format('\StringFileInfo\%.4x%.4x\FileVersion',[lpTranslate^.wLanguage,lpTranslate^.wCodePage]);
VerQueryValue(VerInfo, PAnsiChar(data),Pointer(VerFileV), VerValueSize);
if VerValueSize <> 0 then
begin
SetString(lpFileVersion,VerFileV,VerValueSize-1);
Result:=lpFileVersion;
end;
end;
FreeMem(VerInfo,VerInfoSize);
end
else begin
Result:='0.0.0.0';
Application.MessageBox('获取文件版本信息时遇到致命错误,请重新打开软件。','错误',MB_OK+MB_ICONSTOP);
Application.Terminate;
end;
end;
function KillTask(ExeFileName:string):integer;
const
PROCESS_TERMINATE = $0001;
var
ContinueLoop: BOOLean;
FSnapshotHandle: THandle;
FProcessEntry32: TProcessEntry32;
begin
Result :=0;
FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
while Integer(ContinueLoop) <> 0 do
begin
if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) =
UpperCase(ExeFileName))) then
Result := Integer(TerminateProcess(OpenProcess(PROCESS_TERMINATE,BOOL(0),
FProcessEntry32.th32ProcessID),0));
ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
end;
CloseHandle(FSnapshotHandle);
end;
procedure TUpDateThread.Execute;
var
FindUD:Boolean;
inifile:TiniFile;
i,Num:integer;
DownFile,FSaveFile:String;
Name,Path,CliVersion,SerVersion:String;
begin
FindUD:=False;
inifile:=TiniFile.Create(ExtractFilePath(Application.ExeName)+'UpDate.ini');
Num:=StrToInt(inifile.ReadString('Program Number','Num',''));
for i:=1 to Num do
begin
Name:=inifile.ReadString('session'+inttostr(i),'Name','');
Path:=inifile.ReadString('session'+inttostr(i),'Path','');
SerVersion:=inifile.ReadString('session'+inttostr(i),'Version','');
CliVersion:=ShowVersion;
if (Name=ExtractFileName(Application.ExeName)) and (CliVersion<>SerVersion) then
begin
FindUD:=True;
DownFile:=Path+Name;
SName:=DownFile;
FSaveFile:=Application.ExeName;
break;
end;
end;
try
DeleteFile(ExtractFilePath(Application.ExeName)+Name+'.old');
except
On E:Exception do
Application.MessageBox('删除旧版本失败!','Error',MB_OK);
end;
if FindUD then
begin
if Application.MessageBox('发现一个新版本的软件,是否更新软件?','软件更新',MB_OKCancel)=mrOK then
begin
if Application.MessageBox('请选择更新软件的时间!现在更新点''yes'',关闭软件时更新点''No''','软件更新',MB_YESNO)=mrYes then
begin
Application.MessageBox('软件更新期间请停止对软件的操作,更新成功会自动重新打开程序!','软件更新',MB_OK);
Application.ProcessMessages;
Screen.Cursor:=crHourGlass;
try
ReNameFile(FSaveFile,FSaveFile+'.old');
except
On E:Exception do
Application.MessageBox('拷贝文件副本失败!','Error',MB_OK);
end;
try
URLDownloadToFile(nil,PAnsiChar(DownFile),PAnsiChar(FSaveFile),0,nil);
ShellExecute(0, 'open', PChar(Name),PChar(ExtractFilePath(Application.ExeName)), nil, SW_SHOWNORMAL);
KillTask(ExtractFileName(Application.ExeName));
except
On E:Exception do
begin
ReNameFile(FSaveFile+'.old',FSaveFile);
Application.MessageBox('下载失败!','Error',MB_OK);
Screen.Cursor:=crDefault;
end;
end;
end
else begin
UpGradeB:=True;
end;
end;
end;
iniFile.Free;
end;
procedure KillExe;
var
BatchFile: TextFile;
BatchFileName: string;
ProcessInfo: TProcessInformation;
StartUpInfo: TStartupInfo;
begin
BatchFileName := ExtractFilePath(ParamStr(0)) + '_KillExe.bat';
AssignFile(BatchFile, BatchFileName);
Rewrite(BatchFile);
Writeln(BatchFile, 'del "' + ParamStr(0) + '.old"');
Writeln(BatchFile,
'if exist "' + ParamStr(0) + '.old"' + ' goto try');
Writeln(BatchFile, 'del %0');
CloseFile(BatchFile);
FillChar(StartUpInfo, SizeOf(StartUpInfo), $00);
StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;
StartUpInfo.wShowWindow := SW_HIDE;
if CreateProcess(nil, PChar(BatchFileName), nil, nil,
False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo,
ProcessInfo) then
begin
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
end;
end;
procedure UpGrade;
var
FSaveFile,DownFile:String;
begin
if UpGradeB then
begin
DownFile:=SName;
FSaveFile:=Application.ExeName;
Application.MessageBox('软件更新期间请停止对软件的操作!','软件更新',mb_OK);
Application.ProcessMessages;
Screen.Cursor:=crHourGlass;
try
DeleteFile(FSaveFile+'.old');
except
On E:Exception do
Application.MessageBox('删除旧软件失败!','软件更新',mb_OK);
end;
try
ReNameFile(FSaveFile,FSaveFile+'.old');
except
On E:Exception do
Application.MessageBox('拷贝文件副本失败!','Error',mb_OK);
end;
try
URLDownloadToFile(nil,PAnsiChar(DownFile),PAnsiChar(FSaveFile),0,nil);
Screen.Cursor:=crdefault;
Application.MessageBox('软件更新成功!','软件更新',mb_OK);
except
On E:Exception do
begin
ReNameFile(FSaveFile+'.old',FSaveFile);
Application.MessageBox('更新软件失败,原软件将恢复!','Error',mb_OK);
end;
end;
try
KillExe;
except
On E:Exception do
begin
Application.MessageBox('删除旧软件失败!','Error',mb_OK);
end;
end;
end;
end;
end.