Allow only one installer instance: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
(add Linux support info)
Line 3: Line 3:
== Description ==
== Description ==
The best way is to use a kernel mutex. You can call the Win32 API using the [[System plug-in]]. See also [[CreateMutex plug-in]].
The best way is to use a kernel mutex. You can call the Win32 API using the [[System plug-in]]. See also [[CreateMutex plug-in]].
On Linux this did not work for me (it always thinks it is already running). Tried using GenToo64 and NSIS 2.45. Using the [[CreateMutex plug-in]] works.


Put this code in the .onInit function:
Put this code in the .onInit function:

Revision as of 17:56, 2 August 2009

Author: Vytautas (talk, contrib)


Description

The best way is to use a kernel mutex. You can call the Win32 API using the System plug-in. See also CreateMutex plug-in.

On Linux this did not work for me (it always thinks it is already running). Tried using GenToo64 and NSIS 2.45. Using the CreateMutex plug-in works.

Put this code in the .onInit function:

The Script

  System::Call 'kernel32::CreateMutexA(i 0, i 0, t "myMutex") ?e'
  Pop $R0
  StrCmp $R0 0 +3
    MessageBox MB_OK "The installer is already running."
    Abort

'myMutex' should be replaced with a unique value (e.g. ProgramSetup.exe).

The advanced way

This code will bring the already running instance to front, instead of opening a new one. Side Note (Jamyn): Strangely, if the user has first minimized the installer, and then tries to launch another copy, the following code will correctly set the first installer as the active window, but won't "pop" it back up from being minimized. Not sure how to do that simply, but that may be useful. Note (Rescator): Try something like System::Call "user32::ShowWindow(i r1,i 9) i." The 9 is the flag #SW_RESTORE see PSDK for more info on ShowWindow()

 System::Call "kernel32::CreateMutexA(i 0, i 0, t '$(^Name)') i .r0 ?e"
 Pop $0
 StrCmp $0 0 launch
  StrLen $0 "$(^Name)"
  IntOp $0 $0 + 1
 loop:
   FindWindow $1 '#32770' '' 0 $1
   IntCmp $1 0 +4
   System::Call "user32::GetWindowText(i r1, t .r2, i r0) i."
   StrCmp $2 "$(^Name)" 0 loop
   System::Call "user32::SetForegroundWindow(i r1) i."
   Abort
 launch:

Even more advanced

This uses the "advanced way" method. Unlike the function above, it will maximize the window if the installer is minimized.

Function .onInit
  BringToFront
; Check if already running
; If so don't open another but bring to front
  System::Call "kernel32::CreateMutexA(i 0, i 0, t '$(^Name)') i .r0 ?e"
  Pop $0
  StrCmp $0 0 launch
   StrLen $0 "$(^Name)"
   IntOp $0 $0 + 1
  loop:
    FindWindow $1 '#32770' '' 0 $1
    IntCmp $1 0 +5
    System::Call "user32::GetWindowText(i r1, t .r2, i r0) i."
    StrCmp $2 "$(^Name)" 0 loop
    System::Call "user32::ShowWindow(i r1,i 9) i."         ; If minimized then maximize
    System::Call "user32::SetForegroundWindow(i r1) i."    ; Bring to front
    Abort
  launch:
FunctionEnd