有关 Inno Setup 的实践:检查并安装依赖,运行时退出安装或卸载

如题,检测 Microsoft Visual C++ 2015 Redistributable (x64) 依赖并安装,若程序安装或卸载时应用运行中将检测并退出

所需依赖

编辑 iss 文件

[Files]
...
Source: "psvince_path\psvince.dll"; DestDir: "{app}"

[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent; BeforeInstall: IsAllDependciesInstalled

[Code]
// 通过注册表检测 VC2015+ 是否安装
function IsVCServiceInstalled(): Boolean;
var
  Names: TArrayOfString;
  I: Integer;
  RootKey: Integer;
  Subkey: String; 
begin
  Result := false;
  if IsWin64 then
  begin
    RootKey := HKLM64;
  end
  else
  begin
    RootKey := HKLM32;
  end;
  if RegGetSubKeyNames(RootKey, 'SOFTWARE\Classes\Installer\Dependencies', Names) then
  begin
    for I := 0 to GetArrayLength(Names)-1 do
    begin
      SubKey := Names[I];
      if Pos('VC,redist.x64,amd64,14', Subkey) > 0 then
        begin
          Result := true;  
          Break;
        end
      else
        begin
          Result := false;
        end
    end
  end
end;

// 退出安装程序
procedure ExitProcess(uExitCode: Integer);
  external 'ExitProcess@kernel32.dll stdcall';

// 通过注册表判断所需服务是否安装
procedure IsAllDependciesInstalled;
var
  VCServiceInstalled: Boolean;
  MissingService: String;
  ResultCode: Integer;
begin
  MissingService := '';
  VCServiceInstalled := IsVCServiceInstalled();
  if not VCServiceInstalled then
    MissingService := MissingService + ExpandConstant('{#StringChange(VCServiceName, '&', '&&')}') + #13#10; // #13#10 代表换行

  if not VCServiceInstalled then
  begin
    if MsgBox(FmtMessage(CustomMessage('MissingDependcies'), [MissingService]), mbConfirmation, MB_OKCANCEL) = IDOK then
    begin
      if not VCServiceInstalled then
        Exec(ExpandConstant('{app}\{#VCServiceExeName}'), '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
        // 如果是 .msi 形式安装
        // ShellExec('', 'msiexec.exe', ExpandConstant('/I "{app}\{#VCServiceExeName}" /qb'), '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
    end 
  end
end;

// 检测程序进程是否启动
function IsModuleLoaded2(modulename: String ):  Boolean;
external 'IsModuleLoaded2@files:psvince.dll stdcall setuponly';

// 判断进程是否存在
function IsAppRunning(const FileName : string): Boolean;
var
    FSWbemLocator: Variant;
    FWMIService   : Variant;
    FWbemObjectSet: Variant;
begin
    Result := false;
    try
      FSWbemLocator := CreateOleObject('WBEMScripting.SWBEMLocator');
      FWMIService := FSWbemLocator.ConnectServer('', 'root\CIMV2', '', '');
      FWbemObjectSet := FWMIService.ExecQuery(Format('SELECT Name FROM Win32_Process Where Name="%s"',[FileName]));
      Result := (FWbemObjectSet.Count > 0);
      FWbemObjectSet := Unassigned;
      FWMIService := Unassigned;
      FSWbemLocator := Unassigned;
    except
      if (IsModuleLoaded2(FileName)) then
        begin
          Result := false;
        end
      else
        begin
          Result := true;
        end
      end;
end;

// 通过名称终结进程
procedure TaskKillProcessByName(AppName: String);
var
  WbemLocator : Variant;
  WMIService   : Variant;
  WbemObjectSet: Variant;
  WbemObject   : Variant;
begin;
  WbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  WMIService := WbemLocator.ConnectServer('localhost', 'root\CIMV2');
  WbemObjectSet := WMIService.ExecQuery('SELECT * FROM Win32_Process Where Name="' + AppName + '"');
  if not VarIsNull(WbemObjectSet) and (WbemObjectSet.Count > 0) then
  begin
    WbemObject := WbemObjectSet.ItemIndex(0);
    if not VarIsNull(WbemObject) then
    begin
      WbemObject.Terminate();
      WbemObject := Unassigned;
    end;
  end;
end;

// 安装的时候判断进程是否存在
function InitializeSetup(): Boolean;
begin
 Result := IsAppRunning('{#MyAppExeName}');
  if Result then
  begin
    MsgBox(ExpandConstant('{cm:SetupAppRunningError,{#StringChange(MyAppName, '&', '&&')}}'), mbError, MB_OK); 
    result:=false;
  end
else
    begin
      result := true;
    end;
end;

//;卸载的时候判断进程是否存在
function InitializeUninstall(): Boolean;
begin
 Result := IsAppRunning('{#MyAppExeName}');
  if Result then
  begin
    MsgBox(ExpandConstant('{cm:UninstallAppRunningError,{#StringChange(MyAppName, '&', '&&')}}'), mbError, MB_OK); 
    result:=false;
  end
else
    begin
      result := true;
    end;
end;  





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值