Allow only one installer instance
From NSIS Wiki
Jump to navigationJump to search
Author: Anders (talk, contrib) |
Mutex
A mutex is perhaps the best way to detect if another instance is running:
!define INSTALLERMUTEXNAME "$(^Name)" ; TODO: Should really use a GUID here! (guidgenerator.com or guidgen.com) !ifndef NSIS_PTR_SIZE & SYSTYPE_PTR !define SYSTYPE_PTR i ; NSIS v2.x !else !define /ifndef SYSTYPE_PTR p ; NSIS v3.0+ !endif !macro ActivateOtherInstance StrCpy $3 "" ; Start FindWindow with NULL loop: FindWindow $3 "#32770" "" "" $3 StrCmp 0 $3 windownotfound StrLen $0 "$(^UninstallCaption)" IntOp $0 $0 + 1 ; GetWindowText count includes \0 System::Call 'USER32::GetWindowText(${SYSTYPE_PTR}r3, t.r0, ir0)' StrCmp $0 "$(^UninstallCaption)" windowfound "" StrLen $0 "$(^SetupCaption)" IntOp $0 $0 + 1 ; GetWindowText count includes \0 System::Call 'USER32::GetWindowText(${SYSTYPE_PTR}r3, t.r0, ir0)' StrCmp $0 "$(^SetupCaption)" windowfound loop windowfound: SendMessage $3 0x112 0xF120 0 /TIMEOUT=2000 ; WM_SYSCOMMAND:SC_RESTORE to restore the window if it is minimized System::Call "USER32::SetForegroundWindow(${SYSTYPE_PTR}r3)" windownotfound: !macroend !macro SingleInstanceMutex !ifndef INSTALLERMUTEXNAME !error "Must define INSTALLERMUTEXNAME" !endif System::Call 'KERNEL32::CreateMutex(${SYSTYPE_PTR}0, i1, t"${INSTALLERMUTEXNAME}")?e' Pop $0 IntCmpU $0 183 "" launch launch ; ERROR_ALREADY_EXISTS? !insertmacro ActivateOtherInstance Abort launch: !macroend Function .onInit !insertmacro SingleInstanceMutex FunctionEnd Function un.onInit !insertmacro SingleInstanceMutex FunctionEnd
File
A open file handle that denies shared access can be used to detect a existing instance:
#TODO !define INSTALLERLOCKFILEGUID "{....}" ; Use a GUID here! (guidgenerator.com or guidgen.com) !macro SingleInstanceFile !ifndef INSTALLERLOCKFILEGUID !error "Must define INSTALLERLOCKFILEGUID" !endif !if "${NSIS_PTR_SIZE}" > 4 !include util.nsh !else ifndef IntPtrCmp !define IntPtrCmp IntCmp !endif !ifndef NSIS_PTR_SIZE & SYSTYPE_PTR !define SYSTYPE_PTR i ; NSIS v2.x !else !define /ifndef SYSTYPE_PTR p ; NSIS v3.0+ !endif !if "${NSIS_CHAR_SIZE}" < 2 Push "$TEMP\${INSTALLERLOCKFILEGUID}.lock" !else Push "$APPDATA\${INSTALLERLOCKFILEGUID}.lock" !endif System::Call 'KERNEL32::CreateFile(ts,i0x40000000,i0,${SYSTYPE_PTR}0,i4,i0x04000000,${SYSTYPE_PTR}0)${SYSTYPE_PTR}.r0' ${IntPtrCmp} $0 -1 "" launch launch MessageBox MB_ICONSTOP "Already running!" Abort launch: !macroend Function .onInit !insertmacro SingleInstanceFile FunctionEnd Function un.onInit !insertmacro SingleInstanceFile FunctionEnd