ShellExecEx: Difference between revisions
From NSIS Wiki
Jump to navigationJump to search
No edit summary |
|||
(10 intermediate revisions by 2 users not shown) | |||
Line 3: | Line 3: | ||
== Description == | == Description == | ||
Executes files via the ShellExecuteEx api, uses three modes: 1. nowait | Executes files via the ShellExecuteEx api, uses three modes: 1. nowait - returns process id, 2. nowait - returns process handle, and 3. wait mode - returns process exit code. XP-SP1/2003 or higher is required for mode 1. | ||
== Example == | == Example == | ||
Tests if a process, identified by a handle, still exists. | |||
<highlight-nsis> | <highlight-nsis> | ||
!define IfProcExistsH "!insertmacro _IfProcExistsH" | !define IfProcExistsH "!insertmacro _IfProcExistsH" | ||
!macro _IfProcExistsH _ProcHandle_ _GotoIfTrue_ _GotoIfFalse_ | !macro _IfProcExistsH _ProcHandle_ _GotoIfTrue_ _GotoIfFalse_ ;; gotos: no negative numbers, use labels instead | ||
Push "$0" | Push "$0" | ||
ClearErrors | ClearErrors | ||
System::Call 'kernel32::WaitForSingleObject(i ${_ProcHandle_}, i 0) i .r0' | System::Call 'kernel32::WaitForSingleObject(i ${_ProcHandle_}, i 0) i .r0' ;; no wait, just check if ok | ||
IntCmp $0 0 +2 | IntCmp $0 0 +2 | ||
SetErrors | SetErrors | ||
Line 20: | Line 20: | ||
!macroend | !macroend | ||
${ShellExecEx} $0 '' '"$EXEDIR\test.exe"' '' '' '' 2 | |||
${ShellExecEx} $0 '' '"$EXEDIR\test.exe"' '' '' '' 2 | |||
loop: | loop: | ||
/* some code here */ | /* some code here */ | ||
Line 29: | Line 28: | ||
MessageBox MB_OK "The process doesn't exists anymore!" | MessageBox MB_OK "The process doesn't exists anymore!" | ||
</highlight-nsis> | </highlight-nsis> | ||
== Function == | == Function == | ||
<highlight-nsis> | <highlight-nsis> | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
;; Gets the parent | ;; Gets the parent directory | ||
;; P1 :out: | ;; P1 :out: Parent dir | ||
;; P2 :in: File/Dir | ;; P2 :in: File/Dir | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
Line 62: | Line 60: | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
;; Executes | ;; Executes a file with the ShellExecuteEx api | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
;; P1 :out: Return value, depends on the mode ( | ;; P1 :out: Return value, depends on the mode (P7). On error returns -1 and sets the error flag | ||
;; P2 :in: Verb. if="" then it opens with default associated app | ;; P2 :in: Verb. if="" then it opens with default associated app | ||
;; P3 :in: File | ;; P3 :in: File | ||
Line 71: | Line 69: | ||
;; P6 :in: Show flag. if="" then SH_SHOW is used (http://msdn.microsoft.com/en-us/library/bb762153(v=VS.85).aspx) | ;; P6 :in: Show flag. if="" then SH_SHOW is used (http://msdn.microsoft.com/en-us/library/bb762153(v=VS.85).aspx) | ||
;; P7 :in: Mode: 1=Nowait, Return Process Id | ;; P7 :in: Mode: 1=Nowait, Return Process Id | ||
;; | ;; 2=Nowait, Return Process Handle (must close the handle yourself) | ||
;; | ;; 3=Wait, Return Process Exit Code | ||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
!define ShellExecEx "!insertmacro _ShellExecEx" | !define ShellExecEx "!insertmacro _ShellExecEx" | ||
Line 86: | Line 84: | ||
!macroend | !macroend | ||
Function ShellExecEx | Function ShellExecEx | ||
Exch $0 ;; | Exch $0 ;; Verb | ||
Exch | Exch | ||
Exch $1 ;; File | Exch $1 ;; File | ||
Exch 2 | Exch 2 | ||
Exch $2 ;; Params | Exch $2 ;; Params / process handle | ||
Exch 3 | Exch 3 | ||
Exch $3 ;; WorkDir | Exch $3 ;; WorkDir | ||
Exch 4 | Exch 4 | ||
Exch $4 ;; Show | Exch $4 ;; Show / return value | ||
Exch 5 | Exch 5 | ||
Exch $5 ;; Mode | Exch $5 ;; Mode | ||
Push "$9" ;; shellexecuteinfo struct | Push "$9" ;; shellexecuteinfo struct | ||
ClearErrors | |||
StrCmpS "" "$3" 0 wdok | StrCmpS "" "$3" 0 wdok | ||
${PathPath} $3 "$1" | ${PathPath} $3 "$1" | ||
Line 106: | Line 105: | ||
System::Call '*(&i60) i .r9' ;; allocate the structure | System::Call '*(&i60) i .r9' ;; allocate the structure | ||
System::Call '*$9(i 60, i 0x140, i $HWNDPARENT, t r0, t r1, t r2, t r3, i r4) i .r9' ;; assign the values to the struct | System::Call '*$9(i 60, i 0x140, i $HWNDPARENT, t r0, t r1, t r2, t r3, i r4) i .r9' ;; assign the values to the struct | ||
System::Call ' | System::Call 'shell32::ShellExecuteEx(i r9) i .r1' ;; execute the file | ||
StrCmpS 0 $1 0 +4 ;; if there was errors, then | StrCmpS 0 $1 0 +4 ;; if there was errors, then | ||
StrCpy $ | StrCpy $4 -1 ; return -1 and set the error flag | ||
SetErrors | SetErrors | ||
Goto end | Goto end | ||
System::Call '*$9(i, i, i, i, i, i, i, i, i, i, i, i, i, i, i .r2)' | System::Call '*$9(i, i, i, i, i, i, i, i, i, i, i, i, i, i, i .r2)' ;; get the process handle | ||
IntCmp $5 2 +4 0 +6 ;; 1:nowait-pid, 2:nowait-handle, 3:wait-exitcode | IntCmp $5 2 +4 0 +6 ;; 1:nowait-pid, 2:nowait-handle, 3:wait-exitcode | ||
System::Call ' | System::Call 'kernel32::GetProcessId(i r2) i .r4' | ||
System::Call ' | System::Call 'kernel32::CloseHandle(i r2)' | ||
Goto end | Goto end | ||
; handle: | ; handle: | ||
Line 122: | Line 120: | ||
Goto end | Goto end | ||
; wait: | ; wait: | ||
System::Call ' | System::Call 'kernel32::WaitForSingleObject(i r2, i -1)' ;; wait indefinitely for the process to exit | ||
System::Call ' | System::Call 'kernel32::GetExitCodeProcess(i r2,*i .r4)' | ||
System::Call 'Kernel32::CloseHandle(i r2)' | System::Call 'Kernel32::CloseHandle(i r2)' | ||
Latest revision as of 12:26, 3 December 2011
Author: Lloigor (talk, contrib) |
Description
Executes files via the ShellExecuteEx api, uses three modes: 1. nowait - returns process id, 2. nowait - returns process handle, and 3. wait mode - returns process exit code. XP-SP1/2003 or higher is required for mode 1.
Example
Tests if a process, identified by a handle, still exists.
!define IfProcExistsH "!insertmacro _IfProcExistsH" !macro _IfProcExistsH _ProcHandle_ _GotoIfTrue_ _GotoIfFalse_ ;; gotos: no negative numbers, use labels instead Push "$0" ClearErrors System::Call 'kernel32::WaitForSingleObject(i ${_ProcHandle_}, i 0) i .r0' ;; no wait, just check if ok IntCmp $0 0 +2 SetErrors Pop $0 IfErrors ${_GotoIfTrue_} ${_GotoIfFalse_} !macroend ${ShellExecEx} $0 '' '"$EXEDIR\test.exe"' '' '' '' 2 loop: /* some code here */ ${IfProcExistsH} $0 0 +3 MessageBox MB_OK "The process still exists." Goto loop MessageBox MB_OK "The process doesn't exists anymore!"
Function
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Gets the parent directory ;; P1 :out: Parent dir ;; P2 :in: File/Dir ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; !define PathPath "!insertmacro _PathPath" !macro _PathPath _RetVal_ _Path_ Push "${_Path_}" Call PathPath Pop "${_RetVal_}" !macroend Function PathPath Exch $0 ;; Path Push $1 ;; Strlen / Counter Push $2 ;; Curchar StrLen $1 '$0' IntCmp $1 0 +6 IntOp $1 $1 - 1 StrCpy $2 "$0" 1 $1 StrCmp "$2" '\' +3 StrCmp "$2" ":" 0 -4 IntOp $1 $1 + 1 StrCpy $0 "$0" $1 0 Pop $2 Pop $1 Exch $0 FunctionEnd ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Executes a file with the ShellExecuteEx api ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; P1 :out: Return value, depends on the mode (P7). On error returns -1 and sets the error flag ;; P2 :in: Verb. if="" then it opens with default associated app ;; P3 :in: File ;; P4 :in: File parameters ;; P5 :in: Working directory. if="" then its set to the same dir as the file ;; P6 :in: Show flag. if="" then SH_SHOW is used (http://msdn.microsoft.com/en-us/library/bb762153(v=VS.85).aspx) ;; P7 :in: Mode: 1=Nowait, Return Process Id ;; 2=Nowait, Return Process Handle (must close the handle yourself) ;; 3=Wait, Return Process Exit Code ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; !define ShellExecEx "!insertmacro _ShellExecEx" !macro _ShellExecEx _RetVal_ _Verb_ _File_ _Params_ _WorkDir_ _Show_ _Mode_ Push `${_Mode_}` Push `${_Show_}` Push `${_WorkDir_}` Push `${_Params_}` Push `${_File_}` Push `${_Verb_}` Call ShellExecEx Pop ${_RetVal_} !macroend Function ShellExecEx Exch $0 ;; Verb Exch Exch $1 ;; File Exch 2 Exch $2 ;; Params / process handle Exch 3 Exch $3 ;; WorkDir Exch 4 Exch $4 ;; Show / return value Exch 5 Exch $5 ;; Mode Push "$9" ;; shellexecuteinfo struct ClearErrors StrCmpS "" "$3" 0 wdok ${PathPath} $3 "$1" wdok: StrCmpS "" "$4" 0 +2 ;; if show mode is undefined, then StrCpy $4 0x05 ; = SH_SHOW System::Call '*(&i60) i .r9' ;; allocate the structure System::Call '*$9(i 60, i 0x140, i $HWNDPARENT, t r0, t r1, t r2, t r3, i r4) i .r9' ;; assign the values to the struct System::Call 'shell32::ShellExecuteEx(i r9) i .r1' ;; execute the file StrCmpS 0 $1 0 +4 ;; if there was errors, then StrCpy $4 -1 ; return -1 and set the error flag SetErrors Goto end System::Call '*$9(i, i, i, i, i, i, i, i, i, i, i, i, i, i, i .r2)' ;; get the process handle IntCmp $5 2 +4 0 +6 ;; 1:nowait-pid, 2:nowait-handle, 3:wait-exitcode System::Call 'kernel32::GetProcessId(i r2) i .r4' System::Call 'kernel32::CloseHandle(i r2)' Goto end ; handle: StrCpy $4 "$2" Goto end ; wait: System::Call 'kernel32::WaitForSingleObject(i r2, i -1)' ;; wait indefinitely for the process to exit System::Call 'kernel32::GetExitCodeProcess(i r2,*i .r4)' System::Call 'Kernel32::CloseHandle(i r2)' end: System::Free $9 Pop $9 Pop $5 Pop $0 Pop $1 Pop $2 Pop $3 Exch $4 FunctionEnd