• Delphi实现软件自动更新源代码


     

    关键技术是获取版本号功能和批处理删除自身的功能

    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.

  • 相关阅读:
    IIS------如何占用80端口
    Tomcat------如何更改被IIS占用的80端口
    Tomcat------如何查看80端口是否被占用
    Eclipse------新建文件时没有JSP File解决方法
    jenkins在Linux 下安装部署
    linux ssh免密登陆
    docker login 报错 Error response from daemon: Get https://registry-1.docker.io/v2/: unauthorized: incorrect username or password
    jenkins学习笔记
    docker搭建私有仓库
    解决docker启动错误 error creating overlay mount to /var/lib/docker/overlay2
  • 原文地址:https://www.cnblogs.com/hssbsw/p/3047827.html
Copyright © 2020-2023  润新知