jrsoftware.org // Jordan Russell's Software
-Home

Products

-Inno Setup


-Toolbar2000

-Toolbar97

-StripReloc

-More...

Support

-Newsgroups

-Contact Me

#######
visitors since
Jan. 1998

Inno Setup Knowledge Base
Return to index

HOWTO: Detect instances running in any user session with AppMutex

Article Created: 2003-10-24 00:20 GMT by Jordan Russell
Last Updated: 2003-10-24 01:32 GMT by Jordan Russell


Under Windows XP with Fast User Switching or Windows NT/2000/2003 with Terminal Services, AppMutex by default will not find mutexes created in user sessions other than the one Setup/Uninstall is running under. This is because each user session has its own kernel namespace.

To detect mutexes created in other sessions, your application must create two mutexes: one with a Global\ prefix and the other without.

Mutexes with the Global\ prefix are accessible from any user session. A like-named mutex must also be created in the session namespace (i.e. without the Global\ prefix) in case the creation of the Global mutex failed due to security restrictions or lack of operating system support (versions of Windows NT prior to 4.0 Terminal Server Edition don't support the Global\ prefix).

Additionally, a special security descriptor must be passed in each of the CreateMutex() calls to ensure the mutex is accessible by different users.

Here is an example of how to create the two mutexes in Delphi:

procedure CreateMutexes(const MutexName: String);
{ Creates the two mutexes checked for by the installer/uninstaller to see if
  the program is still running.
  One of the mutexes is created in the global name space (which makes it
  possible to access the mutex across user sessions in Windows XP); the other
  is created in the session name space (because versions of Windows NT prior
  to 4.0 TSE don't have a global name space and don't support the 'Global\'
  prefix). }
const
  SECURITY_DESCRIPTOR_REVISION = 1;  { Win32 constant not defined in Delphi 3 }
var
  SecurityDesc: TSecurityDescriptor;
  SecurityAttr: TSecurityAttributes;
begin
  { By default on Windows NT, created mutexes are accessible only by the user
    running the process. We need our mutexes to be accessible to all users, so
    that the mutex detection can work across user sessions in Windows XP. To
    do this we use a security descriptor with a null DACL. }
  InitializeSecurityDescriptor(@SecurityDesc, SECURITY_DESCRIPTOR_REVISION);
  SetSecurityDescriptorDacl(@SecurityDesc, True, nil, False);
  SecurityAttr.nLength := SizeOf(SecurityAttr);
  SecurityAttr.lpSecurityDescriptor := @SecurityDesc;
  SecurityAttr.bInheritHandle := False;
  CreateMutex(@SecurityAttr, False, PChar(MutexName));
  CreateMutex(@SecurityAttr, False, PChar('Global\' + MutexName));
end;

...

begin
  CreateMutexes('YourMutexNameGoesHere');
end;

In your script, set AppMutex as follows:

[Setup]
AppMutex=YourMutexNameGoesHere,Global\YourMutexNameGoesHere

Site contents Copyright © 1997-2012 Jordan Russell. All rights reserved.