6

I have a Inno Setup project that I want to check if the application is actually running before uninstalling it. I tried many ways but it all fails silently, when running in Windows 7. For example the following script that checks for notepad.exe process using psvince.dll always returns false regardless of Notepad being running or not.

I used psvince.dll in a C# app to check, if it works under Windows 7 and it works without any problem. So my best guess is that installer can not run correctly with UAC enabled.

[Code]
function IsModuleLoaded(modulename: String): Boolean;
external 'IsModuleLoaded@files:psvince.dll stdcall';

function InitializeSetup(): Boolean;
begin
   if(Not IsModuleLoaded('ePub.exe')) then
   begin
       MsgBox('Application is not running.', mbInformation, MB_OK);
       Result := true;
   end
   else
   begin
       MsgBox('Application is already running. Close it before uninstalling.', mbInformation, MB_OK);
       Result := false;
   end
end;
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Hadi Eskandari
  • 25,575
  • 8
  • 51
  • 65

4 Answers4

8

Are you using Unicode Inno Setup? If you are, it should say

function IsModuleLoaded(modulename: AnsiString): Boolean;

since psvince.dll isn't a Unicode dll.

Also the example checks for epub.exe, not notepad.exe.

mlaan
  • 670
  • 4
  • 13
7

You can also try to use WMIService:

procedure FindApp(const AppName: String);
var
  WMIService: Variant;
  WbemLocator: Variant;
  WbemObjectSet: 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
    Log(AppName + ' is up and running');
  end;
end;
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
ariwez
  • 1,309
  • 17
  • 20
5

Inno Setup actually has an AppMutex directive, which is documented in the help. Implementing it requires 2 lines of code.

In the [Setup] section of your iss file you add:

AppMutex=MyProgramsMutexName

And then during your application startup add this line of code:

CreateMutex(NULL, FALSE, "MyProgramsMutexName");
sashoalm
  • 75,001
  • 122
  • 434
  • 781
  • 1
    [Official doc](http://www.jrsoftware.org/iskb.php?mutexsessions) says, that you need two mutexes, to detect instances, launched by other users. – Igor Aug 07 '16 at 20:14
1

You could use this code to check if notepad.exe is running.

[Code]
function IsAppRunning(const FileName: string): Boolean;
var
  FWMIService: Variant;
  FSWbemLocator: Variant;
  FWbemObjectSet: Variant;
begin
  Result := false;
  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;
end;

function InitializeSetup: boolean;
begin
  Result := not IsAppRunning('notepad.exe');
  if not Result then
  MsgBox('notepad.exe is running. Please close the application before running the installer ', mbError, MB_OK);
end;
TLama
  • 75,147
  • 17
  • 214
  • 392
Andrew Seaford
  • 645
  • 6
  • 13
  • 3
    How is this different from [`this post`](http://stackoverflow.com/a/24181158/960757) ? Well, it is. You don't need to assign `Unassigned` to the objects since they will be *released* when they go out of scope of the function. And you should check for assignment after you run the query (`VarIsNull` in the other post). So, the other post is a bit shorter and more precise. – TLama Feb 24 '15 at 07:18
  • I've been using this code successfully for ages until today when one user who hadn't seen any error messages before suddenly started seeing two error messages "ShellExecuteEx Failed; code 299. Only part oif a ReadProcessMemory or WriteProcessMemory request was completed." and "Runtime Error (at 1:321); SWbemlocator: Access is denied." – Jamie Garroch - MVP Jun 13 '19 at 14:01