关键技术是获取版本号功能和批处理删除自身的功能
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.
|
请发表评论