inno setup 安装建立回滚机制

目的

安装包在安装过程中可能因为环境或者其他特殊原因安装失败了,但是不能影响以前安装的旧版本,所以就需要建立回滚机制,当安装失败的时候自动复原到以前的版本

实现步骤

  • 在安装之前,拷贝安装目录下的文件到缓存目录,或者移动安装目录下的文件到缓存目录
  • 安装完成之后判断,是否安装成功
  • 如果安装成功
    • 删除缓存目录
  • 如果安装失败
    • 把安装目录下的文件删除,从缓存目录拷贝文件到安装目录下
    • 删除缓存目录

代码

定义全局变量

var
    isInstallSuccess:boolean; //用于判断是否安装成功
    tmpDir:String;       //缓存文件目录

移动目录

首先封装一个移动文件夹的函数

procedure DirectoryMove(SourcePath, DestPath: string);
var
  FindRec: TFindRec;
  SourceFilePath: string;
  DestFilePath: string;
begin
  if FindFirst(SourcePath + '\*', FindRec) then
  begin
    try
      repeat
        if (FindRec.Name <> '.') and (FindRec.Name <> '..') then
        begin
          SourceFilePath := SourcePath + '\' + FindRec.Name;
          DestFilePath := DestPath + '\' + FindRec.Name;
          if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
          begin
            if RenameFile(SourceFilePath, DestFilePath) then
            begin
              Log(Format('Copied %s to %s', [SourceFilePath, DestFilePath]));
            end
              else
            begin
              Log(Format('Failed to copy %s to %s', [SourceFilePath, DestFilePath]));
            end;
          end
            else
          begin
            if DirExists(DestFilePath) or CreateDir(DestFilePath) then
            begin
              Log(Format('Created %s', [DestFilePath]));
              DirectoryMove(SourceFilePath, DestFilePath);
            end
              else
            begin
              Log(Format('Failed to create %s', [DestFilePath]));
            end;
          end;
        end;
      until not FindNext(FindRec);
    finally
      FindClose(FindRec);
    end;
  end
    else
  begin
    Log(Format('Failed to list %s', [SourcePath]));
  end;
end;

//拷贝现有工程目录下的文件到缓存目录
function copyAppFile(strInstallPath:String):Boolean;
begin
  tmpDir := ExpandConstant('{tmp}\CloudHubXSetupBackup');

  if DirExists(tmpDir)= true then  //如果文件夹存在那么先删除文件夹
    DelTree(tmpDir, False, True, True) //删除他下面所有的文件以及目录但是保存本身的目录
  else  //不存在那么先创建目录
    CreateDir(tmpDir);

  if DirExists(strInstallPath)= true then  //存在才拷贝
     DirectoryMove(strInstallPath,tmpDir);

end;

回滚文件

function rollBackFile(strInstallPath:String):Boolean;
begin

  if DirExists(tmpDir)= true then  //存在才移动
     DirectoryMove(tmpDir,strInstallPath);

end;

删除临时目录

function delRollBakcFileDir():Boolean;
begin
  if DirExists(tmpDir)= true then  //存在才删除
     DelTree(tmpDir, True, True, True);  
end;

判断

procedure CurStepChanged (CurStep: TSetupStep );
begin
    if(CurStep = ssDone ) then //最后安装程序退出之前
    begin
        if(isInstallSuccess = false) then  //如果异常退出那么还原文件
        begin
          MsgBox('{#MyAppNameZh}更新包异常退出', mbInformation, MB_OK);
          //回滚文件
          rollBackFile(oldinstallpath);
        end;
        //删除tmp文件夹内的文件
        delRollBakcFileDir();
    end
    else if(CurStep = ssPostInstall  ) then //实际安装完成之后
    begin
        isInstallSuccess := true;
    end
    else if(CurStep=ssInstall) then //开始执行安装之前
    begin
        //执行文件备份
        copyAppFile(oldinstallpath);
    end;
end;

总结

这里安装目录下没有对某些特殊的文件做屏蔽处理,根据需求可以做某些文件不放入回滚机制中,
使用移动文件的方式可以有效的减少innosetup安装过程中出现的文件被占用问题


   转载规则


《inno setup 安装建立回滚机制》 Smoking 采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
  目录