1

I have an install script with Pascal code to determine if the app to be installed is currently running:

; 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;

This works for 99% of the cases but every now and then users report a false positive and are unable to proceed with installation.

Users report that in command line tasklist /FI "IMAGENAME eq MyApp.exe" /FO CSV (which is used by the Pascal script) is returning nothing.

Is there an error in the script that may give false positives or is there a better way to determine if the app is running than tasklist?

Jens A. Koch
  • 39,862
  • 13
  • 113
  • 141
thomiel
  • 2,467
  • 22
  • 37
  • Also see my question http://stackoverflow.com/questions/30617253 if you are an Inno-Setup crack! – thomiel Jun 03 '15 at 10:39
  • 1
    Personally, I would not suggest using this approach if you are in control of the app being installed. You can have the app create a named mutex for the installer to detect, and then the installer can broadcast a custom message for the app to detect to shut itself down before the installer continues. – Remy Lebeau Jun 06 '15 at 06:13
  • Just to expand on @Remy's idea. When your application can create a named mutex, you can simply set [`AppMutex`](http://www.jrsoftware.org/ishelp/index.php?topic=setup_appmutex) directive to the name of that mutex and let the Inno Setup do what installers usually do, they check if there's a mutex of that name and ask the user to exit the application (they don't forcibly terminate it behind the user's back). – TLama Jun 16 '15 at 07:36

1 Answers1

3

Is there an error in the script that may give false positives?

No error.

Are you aware, that tasklist might not be available? Think of "XP Home" (yes, it's fading out), but still in use and your solution will not work there, because tasklist is simply not available.

Or is there a better way to determine if the app is running than 'tasklist'?

Yes, there are some other and maybe more reliable ways to do this. For instance, it's quite common to include psvince in the installer and use it for process detection. Quite nice is also the WMI based solution.

Here are some approaches for "process detection" with InnoSetup:

Community
  • 1
  • 1
Jens A. Koch
  • 39,862
  • 13
  • 113
  • 141
  • 2
    Further exploration of how to check for running apps at this answer: http://stackoverflow.com/a/1577129/550712. – Mark Berry Jan 06 '16 at 02:22