Inno setup 如何在执行InnoSetup安装脚本之前确定应用程序是否正在运行

Inno setup 如何在执行InnoSetup安装脚本之前确定应用程序是否正在运行,inno-setup,win32-process,pascalscript,tasklist,Inno Setup,Win32 Process,Pascalscript,Tasklist,我有一个带有Pascal代码的安装脚本,用于确定要安装的应用程序当前是否正在运行: ; Script generated by the Inno Setup Script Wizard. ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! [Setup] AppName=MyApp AppVerName=MyApp v1.0 DiskSpanning=no AppPublisher=me AppPub

我有一个带有Pascal代码的安装脚本,用于确定要安装的应用程序当前是否正在运行:

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

[Setup]
AppName=MyApp
AppVerName=MyApp v1.0
DiskSpanning=no
AppPublisher=me
AppPublisherURL=http://www.example.com
AppSupportURL=http://www.example.com
AppUpdatesURL=http://www.example.com
DefaultDirName={pf}\MyApp
UsePreviousAppDir=yes
DefaultGroupName=MyApp
OutputBaseFilename=Setup
OutputDir=.\MyAppSetup
MinVersion=5.0

[Tasks]
Name: desktopicon; Description: Create a &desktop icon; GroupDescription: Additional icons:; MinVersion: 4,4

[Files]
Source: .\Release\MyApp.exe; DestDir: {app}; Flags: ignoreversion

[Icons]
Name: {group}\EasyCash&Tax; Filename: {app}\MyApp.exe
Name: {userdesktop}\EasyCash&Tax; Filename: {app}\MyApp.exe; MinVersion: 4,4; Tasks: desktopicon

[Run]
Filename: {app}\MyApp.exe; Description: Launch MyApp; Flags: nowait postinstall skipifsilent

[Code]

function CheckProcessRunning( aProcName,
                              aProcDesc: string ): boolean;
var
  ShellResult: boolean;
  ResultCode: integer;
  cmd: string;
  sl: TStringList;
  f: string;
  d: string;
begin
  cmd := 'for /f "delims=," %%i ' + 
         'in (''tasklist /FI "IMAGENAME eq ' + aProcName + '" /FO CSV'') ' + 
         'do if "%%~i"=="' + aProcName + '" exit 1'; 
  f := 'CheckProc.cmd';
  d := AddBackSlash( ExpandConstant( '{tmp}' ));
  sl := TStringList.Create;
  sl.Add( cmd );
  sl.Add( 'exit /0' );
  sl.SaveToFile( d + f );
  sl.Free;
  Result := true;
  while ( Result ) do
  begin
    ResultCode := 1;
    ShellResult := Exec( f,
                         '',
                         d, 
                         SW_HIDE, 
                         ewWaitUntilTerminated, 
                         ResultCode );
    Result := ResultCode > 0;
    if Result and 
       ( MsgBox( aProcDesc + ' is active and must be closed to proceed', 
                 mbConfirmation, 
                 MB_OKCANCEL ) <> IDOK ) then
      Break;
  end;
  DeleteFile( d + f );
end;

// Perform some initializations.  Return False to abort setup
function InitializeSetup: Boolean;
begin
  // Do not use any user defined vars in here such as {app}
  Result := not ( CheckProcessRunning( 'MyApp.exe',      'MyApp' ));
end;


function InitializeUninstall: Boolean;
begin
  Result := not ( CheckProcessRunning( 'MyApp.exe',      'MyApp' ));
end;
;由Inno安装脚本向导生成的脚本。
; 有关创建INNO安装脚本文件的详细信息,请参阅文档!
[设置]
AppName=MyApp
AppVerName=MyApp v1.0
磁盘扩展=否
AppPublisher=me
APPRURL=http://www.example.com
AppSupportURL=http://www.example.com
AppUpdatesURL=http://www.example.com
DefaultDirName={pf}\MyApp
UsePreviousAppDir=是
DefaultGroupName=MyApp
OutputBaseFilename=设置
OutputDir=。\MyAppSetup
MinVersion=5.0
[任务]
名称:桌面图标;描述:创建桌面图标(&T);组说明:其他图标:;最小版本:4,4
[档案]
来源:。\Release\MyApp.exe;DestDir:{app};标志:忽略版本
[图标]
名称:{group}\EasyCash&Tax;文件名:{app}\MyApp.exe
名称:{userdesktop}\EasyCash&Tax;文件名:{app}\MyApp.exe;最小版本:4,4;任务:桌面图标
[运行]
文件名:{app}\MyApp.exe;说明:启动MyApp;标志:nowait POSTALL skipifsilent
[守则]
函数CheckProcessRunning(aProcName,
aProcDesc:string):布尔值;
变量
结果:布尔;
结果代码:整数;
cmd:字符串;
sl:TStringList;
f:字符串;
d:弦;
开始
cmd:=“对于/f”delims=,“%%i”+
'在('tasklist/FI'IMAGENAME eq'+aProcName+'/FO CSV'')中'+
'如果“%%~i”='+aProcName+'“退出1”,则执行该操作;
f:=“CheckProc.cmd”;
d:=addbackslax(ExpandConstant('{tmp}'));
sl:=TStringList.Create;
sl.Add(cmd);
sl.Add('exit/0');
sl.SaveToFile(d+f);
sl.免费;
结果:=真;
而(结果)呢
开始
结果代码:=1;
ShellResult:=Exec(f,
'',
D
藏起来,
ewwaitunterminated,
结果代码);
结果:=ResultCode>0;
如果结果和
(MsgBox(aProcDesc+“处于活动状态,必须关闭才能继续”,
确认,
(好的,取消)我知道
打破
结束;
删除文件(d+f);
结束;
//执行一些初始化。返回False以中止安装
函数初始化设置:布尔;
开始
//不要在此处使用任何用户定义的变量,例如{app}
结果:=不(CheckProcessRunning('MyApp.exe','MyApp');
结束;
函数初始化安装:布尔值;
开始
结果:=不(CheckProcessRunning('MyApp.exe','MyApp');
结束;
这适用于99%的情况,但用户偶尔会报告假阳性,无法继续安装

用户报告在命令行
任务列表/FI“IMAGENAME eq MyApp.exe”/FO CSV
(由Pascal脚本使用)中没有返回任何内容

脚本中是否存在可能导致误报的错误,或者是否有比
tasklist
更好的方法来确定应用程序是否正在运行

脚本中是否存在可能导致误报的错误

没有错误

您是否知道,
tasklist
可能不可用?想想“XP Home”(是的,它正在淡出),但仍然在使用,您的解决方案在那里无法工作,因为
tasklist
根本不可用

或者有没有比“任务列表”更好的方法来确定应用程序是否正在运行

是的,还有其他一些方法,也许更可靠。例如,在安装程序中包含
psvince
并将其用于进程检测是很常见的。非常好的解决方案也是基于
WMI
的解决方案

以下是使用InnoSetup进行“流程检测”的一些方法:

  • AppMutex-
  • PSVince
  • PSVince Fork
  • 没有外部DLL
  • WMI+Win32\u进程+
  • ProcessViewer

如果您是Inno安装高手,也可以查看我的问题!就个人而言,如果你能控制正在安装的应用程序,我不建议你使用这种方法。你可以让应用程序为安装程序创建一个命名的互斥来检测,然后安装程序可以广播一条自定义消息,让应用程序在安装程序继续之前自动关闭。这只是为了扩展@Remy的想法。当您的应用程序可以创建一个命名的互斥体时,您只需将指令设置为该互斥体的名称,并让Inno安装程序执行安装程序通常执行的操作,安装程序会检查是否存在该名称的互斥体,并要求用户退出应用程序(不会在用户背后强行终止)。进一步探索如何在此答案处检查正在运行的应用程序:。