How to determine with certainty if an appliction is running before InnoSetup install script is executed
Asked Answered
O

1

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?

Ornate answered 3/6, 2015 at 10:38 Comment(3)
Also see my question stackoverflow.com/questions/30617253 if you are an Inno-Setup crack!Ornate
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.Quetzalcoatl
Just to expand on @Remy's idea. When your application can create a named mutex, you can simply set 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).Lashaunda
C
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:

Coraleecoralie answered 15/6, 2015 at 18:14 Comment(1)
Further exploration of how to check for running apps at this answer: https://mcmap.net/q/487135/-uninstall-fails-because-program-is-running-how-do-i-make-inno-setup-check-for-running-process-prior-to-attempting-delete.Borges

© 2022 - 2024 — McMap. All rights reserved.