Get process info: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
mNo edit summary
No edit summary
 
(5 intermediate revisions by 3 users not shown)
Line 1: Line 1:
== Description ==
== Description ==
Get process info by process id
Get process info by process id (0 - current process)
* Real process id (useful for current process)
* Parent pid
* Parent pid
* Priority
* Priority
* process name
* Process name
* Fully-qualified process name (with path)
 
Warning: if you're using this from an uninstaller to get information about the currently running process, you will get unexpected e.g. file names since the NSIS uninstaller copies itself to a temporary folder with a weird name so that the original uninstaller can be deleted.


== Usage ==
== Usage ==
Line 13: Line 17:


Section
Section
${GetProcessInfo} 0 $0 $1 $2 $3
;get own process info
MessageBox MB_OK "r0=$0 r1=$1 r2=$2 r3=$3"  
${GetProcessInfo} 0 $0 $1 $2 $3 $4
;return r0=pid, r1=parent pid, r2=priority, r3=process name
DetailPrint "pid=$0 parent_pid=$1 priority=$2 name=$3 fullname=$4"
 
;and now get parent process info!
${GetProcessInfo} $1 $0 $1 $2 $3 $5
DetailPrint "pid=$0 parent_pid=$1 priority=$2 name=$3 fullname=$4"
;woila
SectionEnd
SectionEnd
</highlight-nsis>
</highlight-nsis>
Line 21: Line 30:
== The Script ==
== The Script ==


[[File:GetProcessInfo.nsh]]
[[File:GetProcessInfo.nsh|Download GetProcessInfo.nsh]]


File content:
File content:
<highlight-nsis>
<highlight-nsis>
;get process information
; NSIS PROCESS INFO LIBRARY - GetProcessInfo.nsh
; Version 1.1 - Mar 28th, 2011
;
; Description:
;  Gets process information.
;
;
;Usage example:
; Usage example:
;${GetProcessInfo} 0 $0 $1 $2 $3
;   ${GetProcessInfo} 0 $0 $1 $2 $3 $4
;DetailPrint "r0=$0 r1=$1 r2=$2 r3=$3" ;return r0=pid, r1=parent pid, r2=priority, r3=process name
;   DetailPrint "pid=$0 parent_pid=$1 priority=$2 process_name=$3 exe=$4"
;
; History:
;   1.1 - 28/03/2011 - Added uninstall function, include guards, file header. Fixed getting full exe path on pre vista systems. (Sergius)
;
;


!ifndef GETPROCESSINFO_INCLUDED
!define GETPROCESSINFO_INCLUDED
!define PROCESSINFO.TH32CS_SNAPPROCESS      2
!define PROCESSINFO.INVALID_HANDLE_VALUE    -1
   
!define GetProcessInfo '!insertmacro GetProcessInfo'
!define GetProcessInfo '!insertmacro GetProcessInfo'


Line 39: Line 61:
;@out priority
;@out priority
;@out name - name of process
;@out name - name of process
!macro GetProcessInfo pid_in pid_out ppid priority name
;@out fullname - fully-qualified path of process
Push ${pid_in}
!macro GetProcessInfo pid_in pid_out ppid priority name fullname
Call _GetProcessInfo
    Push ${pid_in}
Pop ${pid_out}
    !ifdef __UNINSTALL__
Pop ${ppid}
        Call un._GetProcessInfo
Pop ${priority}
    !else
Pop ${name}
        Call _GetProcessInfo
    !endif   
    ;name;pri;ppid;fname;pid;
    Pop ${name}
    Pop ${priority}
    Pop ${ppid}
    Pop ${fullname}
    Pop ${pid_out}
!macroend
!macroend
!macro FUNC_GETPROCESSINFO
    Exch $R3 ;pid
    Push $0
    Push $1
    Push $2
    Push $3
    Push $4
    Push $5
    Push $R0 ;hSnapshot
    Push $R1 ;result
    Push $R9 ;PROCESSENTRY32;MODULEENTRY32 and so on
    Push $R8
    ;zero registers to waste trash, if error occurred
    StrCpy $0 ""
    StrCpy $1 ""
    StrCpy $2 ""
    StrCpy $3 ""
    StrCpy $4 ""
    StrCpy $5 ""
    IntCmp $R3 0 0 skip_pid_detection skip_pid_detection
    System::Call 'kernel32::GetCurrentProcess() i.R0'
    System::Call "Kernel32::GetProcessId(i R0) i.R3"
skip_pid_detection:
    System::Call 'Kernel32::CreateToolhelp32Snapshot(i ${PROCESSINFO.TH32CS_SNAPPROCESS},i R3) i.R0'
    IntCmp $R0 ${PROCESSINFO.INVALID_HANDLE_VALUE} end ;someting wrong
    ;$R9=PROCESSENTRY32
    ;typedef struct tagPROCESSENTRY32 {
    ;  DWORD    dwSize;
    ;  DWORD    cntUsage;
    ;  DWORD    th32ProcessID;
    ;  ULONG_PTR th32DefaultHeapID;
    ;  DWORD    th32ModuleID;
    ;  DWORD    cntThreads;
    ;  DWORD    th32ParentProcessID;
    ;  LONG      pcPriClassBase;
    ;  DWORD    dwFlags;
    ;  TCHAR    szExeFile[MAX_PATH];
    ;}PROCESSENTRY32, *PPROCESSENTRY32;
    ;dwSize=4*9+260
    System::Alloc 1024
    pop $R9
    System::Call "*$R9(i 296)"
    System::Call 'Kernel32::Process32First(i R0, i $R9) i.R1'
    StrCmp $R1 0 end
nnext_iteration:
    System::Call "*$R9(i,i,i.R1)" ;get PID
    IntCmp $R1 $R3 exitloop
    System::Call 'Kernel32::Process32Next(i R0, i $R9) i.R1'
    IntCmp $R1 0 0 nnext_iteration nnext_iteration
exitloop:
    ;$0 - pid
    ;$1 - threads
    ;$2 - ppid
    ;$3 - priority
    ;$4 - process name
    System::Call "*$R9(i,i,i.r0,i,i,i.r1,i.r2,i.r3,i,&t256.r4)" ; Get next module
    ;free:
    System::Free $R9
    System::Call "Kernel32::CloseToolhelp32Snapshot(i R0)"
    ;===============
    ;now get full path and commandline
    System::Call "Kernel32::OpenProcess(i 1040, i 0, i r0)i .R0"
    StrCmp $R0 0 end
    IntOp $R8 0 + 256
    System::Call "psapi::GetModuleFileNameEx(i R0,i 0,t .r5, *i $R8)i .R1"
end:
    Pop $R8
    Pop $R9
    Pop $R1
    Pop $R0
    Exch $5
    Exch 1
    Exch $4
    Exch 2 
    Exch $3
    Exch 3
    Exch $2
    Exch 4
    Pop $1
    Exch 4
    Exch $0
    Exch 5 
    Pop $R3
!macroend ;FUNC_GETPROCESSINFO


Function _GetProcessInfo
Function _GetProcessInfo
Exch $R3 ;pid
    !insertmacro FUNC_GETPROCESSINFO
Push $R0 ;hSnapshot
FunctionEnd
Push $R1 ;result
 
Push $R9 ;PROCESSENTRY32
Function un._GetProcessInfo
Push $0
    !insertmacro FUNC_GETPROCESSINFO
Push $1
FunctionEnd
Push $2
 
Push $3
!endif ;GETPROCESSINFO_INCLUDED</highlight-nsis>
Push $4
 
== Version for Unicode NSIS ==
!define TH32CS_SNAPPROCESS 2
<highlight-nsis>
!define INVALID_HANDLE_VALUE -1
; NSIS PROCESS INFO LIBRARY - GetProcessInfo.nsh
; Version 1.1 - Mar 28th, 2011
;
; Description:
;  Gets process information.
;
; Usage example:
;  ${GetProcessInfo} 0 $0 $1 $2 $3 $4
;  DetailPrint "pid=$0 parent_pid=$1 priority=$2 process_name=$3 exe=$4"
;
; History:
;  1.1 - 28/03/2011 - Added uninstall function, include guards, file header. Fixed getting full exe path on pre vista systems. (Sergius)
;
 
!ifndef GETPROCESSINFO_INCLUDED
!define GETPROCESSINFO_INCLUDED
 
!define PROCESSINFO.TH32CS_SNAPPROCESS      2
!define PROCESSINFO.INVALID_HANDLE_VALUE    -1
   
!define GetProcessInfo '!insertmacro GetProcessInfo'
 
;@in pid_in - if 0 - get current process info
;@out pid_out - real process id (may be useful, if pid_in=0)
;@out ppid - parent process id
;@out priority
;@out name - name of process
;@out fullname - fully-qualified path of process
!macro GetProcessInfo pid_in pid_out ppid priority name fullname
    Push ${pid_in}
    !ifdef __UNINSTALL__
        Call un._GetProcessInfo
    !else
        Call _GetProcessInfo
    !endif   
    ;name;pri;ppid;fname;pid;
    Pop ${name}
    Pop ${priority}
    Pop ${ppid}
    Pop ${fullname}
    Pop ${pid_out}
!macroend
 
!macro FUNC_GETPROCESSINFO
    Exch $R3 ;pid
    Push $0
    Push $1
    Push $2
    Push $3
    Push $4
    Push $5
    Push $R0 ;hSnapshot
    Push $R1 ;result
    Push $R9 ;PROCESSENTRY32;MODULEENTRY32 and so on
    Push $R8
 
    ;zero registers to waste trash, if error occurred
    StrCpy $0 ""
    StrCpy $1 ""
    StrCpy $2 ""
    StrCpy $3 ""
    StrCpy $4 ""
    StrCpy $5 ""
 
    IntCmp $R3 0 0 skip_pid_detection skip_pid_detection
    System::Call 'kernel32::GetCurrentProcess() i.R0'
    System::Call "Kernel32::GetProcessId(i R0) i.R3"


IntCmp $R3 0 0 skip_pid_detection
System::Call 'kernel32::GetCurrentProcess() i.R0'
System::Call "Kernel32::GetProcessId(i R0) i.R3"
skip_pid_detection:
skip_pid_detection:
System::Call 'Kernel32::CreateToolhelp32Snapshot(i ${TH32CS_SNAPPROCESS},i $R3) i.R0'
    System::Call 'Kernel32::CreateToolhelp32Snapshot(i ${PROCESSINFO.TH32CS_SNAPPROCESS},i R3) i.R0'


IntCmp $R0 ${INVALID_HANDLE_VALUE} end ;someting wrong
    IntCmp $R0 ${PROCESSINFO.INVALID_HANDLE_VALUE} end ;someting wrong


;$R9=PROCESSENTRY32
    ;$R9=PROCESSENTRY32
;typedef struct tagPROCESSENTRY32 {
    ;typedef struct tagPROCESSENTRY32 {
;  DWORD    dwSize;
    ;  DWORD    dwSize;
;  DWORD    cntUsage;
    ;  DWORD    cntUsage;
;  DWORD    th32ProcessID;
    ;  DWORD    th32ProcessID;
;  ULONG_PTR th32DefaultHeapID;
    ;  ULONG_PTR th32DefaultHeapID;
;  DWORD    th32ModuleID;
    ;  DWORD    th32ModuleID;
;  DWORD    cntThreads;
    ;  DWORD    cntThreads;
;  DWORD    th32ParentProcessID;
    ;  DWORD    th32ParentProcessID;
;  LONG      pcPriClassBase;
    ;  LONG      pcPriClassBase;
;  DWORD    dwFlags;
    ;  DWORD    dwFlags;
;  TCHAR    szExeFile[MAX_PATH];
    ;  TCHAR    szExeFile[MAX_PATH];
;}PROCESSENTRY32, *PPROCESSENTRY32;
    ;}PROCESSENTRY32, *PPROCESSENTRY32;
;dwSize=4*9+260
    ;dwSize=4*9+2*260


System::Alloc 296
    System::Alloc 1024
pop $R9
    pop $R9
System::Call "*$R9(i 296)"
    System::Call "*$R9(i 556)"


System::Call 'Kernel32::Process32First(i R0, i $R9) i.R1'
    System::Call 'Kernel32::Process32FirstW(i R0, i $R9) i.R1'
    StrCmp $R1 0 end


nnext_iteration:
nnext_iteration:
  System::Call "*$R9(i,i,i.R1)" ;get PID
    System::Call "*$R9(i,i,i.R1)" ;get PID
  IntCmp $R1 $R3 exitloop
    IntCmp $R1 $R3 exitloop


  System::Call 'Kernel32::Process32Next(i R0, i $R9) i.R1'
    System::Call 'Kernel32::Process32NextW(i R0, i $R9) i.R1'
  IntCmp $R1 0 0 nnext_iteration nnext_iteration
    IntCmp $R1 0 0 nnext_iteration nnext_iteration


exitloop:
exitloop:
;$0 - pid
    ;$0 - pid
;$1 - threads
    ;$1 - threads
;$2 - ppid
    ;$2 - ppid
;$3 - priority
    ;$3 - priority
;$4 - process name
    ;$4 - process name
System::Call "*$R9(i,i,i.r0,i,i,i.r1,i.r2,i.r3,i,&t256.r4)" ; Get next module
    System::Call "*$R9(i,i,i.r0,i,i,i.r1,i.r2,i.r3,i,&w256.r4)" ; Get next module


free:
    ;free:
System::Free $R9
    System::Free $R9
    System::Call "Kernel32::CloseToolhelp32Snapshot(i R0)"
 
    ;===============
    ;now get full path and commandline
 
    System::Call "Kernel32::OpenProcess(i 1040, i 0, i r0)i .R0"
 
    StrCmp $R0 0 end
 
    IntOp $R8 0 + 256
    System::Call "psapi::GetModuleFileNameExW(i R0,i 0,t .r5, *i $R8)i .R1"


end:
end:
    Pop $R8
    Pop $R9
    Pop $R1
    Pop $R0
    Exch $5
    Exch 1
    Exch $4
    Exch 2 
    Exch $3
    Exch 3
    Exch $2
    Exch 4
    Pop $1
    Exch 4
    Exch $0
    Exch 5 
    Pop $R3
!macroend ;FUNC_GETPROCESSINFO
Function _GetProcessInfo
    !insertmacro FUNC_GETPROCESSINFO
FunctionEnd


Exch $4 ;name;3;2;1;0
Function un._GetProcessInfo
Exch 1  ;3;name;2;1;0
    !insertmacro FUNC_GETPROCESSINFO
Exch $3 ;pri;name;2;1;0
FunctionEnd
Exch 2 ;2;pri;name;1;0
 
Exch $2 ;ppid;pri;name;1;0
!endif ;GETPROCESSINFO_INCLUDED
Exch 3  ;1;ppid;pri;name;0
</highlight-nsis>
Pop $1  ;ppid;pri;name;0
Exch 3
Exch $0 ;pid;ppid;pri;name;R9;R1;R0;R3
Exch 4
Pop $R9 ;pid;ppid;pri;name;R1;R0;R3
Exch 4
Pop $R1
Exch 4
Pop $R0 ;pid;ppid;pri;name;R3
Exch 4
Pop $R3
FunctionEnd</highlight-nsis>


[[Category:System Plugin Examples]]
[[Category:System Plugin Examples]]

Latest revision as of 03:47, 26 April 2011

Description

Get process info by process id (0 - current process)

  • Real process id (useful for current process)
  • Parent pid
  • Priority
  • Process name
  • Fully-qualified process name (with path)

Warning: if you're using this from an uninstaller to get information about the currently running process, you will get unexpected e.g. file names since the NSIS uninstaller copies itself to a temporary folder with a weird name so that the original uninstaller can be deleted.

Usage

!include GetProcessInfo.nsh
 
OutFile GetProcessInfo.exe
 
Section
 ;get own process info
 ${GetProcessInfo} 0 $0 $1 $2 $3 $4
 DetailPrint "pid=$0 parent_pid=$1 priority=$2 name=$3 fullname=$4"
 
 ;and now get parent process info!
 ${GetProcessInfo} $1 $0 $1 $2 $3 $5
 DetailPrint "pid=$0 parent_pid=$1 priority=$2 name=$3 fullname=$4"
 ;woila
SectionEnd

The Script

File:GetProcessInfo.nsh

File content:

; NSIS PROCESS INFO LIBRARY - GetProcessInfo.nsh
; Version 1.1 - Mar 28th, 2011
;
; Description:
;   Gets process information.
;
; Usage example:
;   ${GetProcessInfo} 0 $0 $1 $2 $3 $4
;   DetailPrint "pid=$0 parent_pid=$1 priority=$2 process_name=$3 exe=$4"
;
; History:
;   1.1 - 28/03/2011 - Added uninstall function, include guards, file header. Fixed getting full exe path on pre vista systems. (Sergius)
;
 
!ifndef GETPROCESSINFO_INCLUDED
!define GETPROCESSINFO_INCLUDED
 
!define PROCESSINFO.TH32CS_SNAPPROCESS      2
!define PROCESSINFO.INVALID_HANDLE_VALUE    -1
 
!define GetProcessInfo '!insertmacro GetProcessInfo'
 
;@in pid_in - if 0 - get current process info
;@out pid_out - real process id (may be useful, if pid_in=0)
;@out ppid - parent process id
;@out priority
;@out name - name of process
;@out fullname - fully-qualified path of process
!macro GetProcessInfo pid_in pid_out ppid priority name fullname
    Push ${pid_in}
    !ifdef __UNINSTALL__
        Call un._GetProcessInfo
    !else
        Call _GetProcessInfo
    !endif    
    ;name;pri;ppid;fname;pid;
    Pop ${name}
    Pop ${priority}
    Pop ${ppid}
    Pop ${fullname}
    Pop ${pid_out}
!macroend
 
!macro FUNC_GETPROCESSINFO
    Exch $R3 ;pid
    Push $0
    Push $1
    Push $2
    Push $3
    Push $4
    Push $5
    Push $R0 ;hSnapshot
    Push $R1 ;result
    Push $R9 ;PROCESSENTRY32;MODULEENTRY32 and so on
    Push $R8
 
    ;zero registers to waste trash, if error occurred
    StrCpy $0 ""
    StrCpy $1 ""
    StrCpy $2 ""
    StrCpy $3 ""
    StrCpy $4 ""
    StrCpy $5 ""
 
    IntCmp $R3 0 0 skip_pid_detection skip_pid_detection
    System::Call 'kernel32::GetCurrentProcess() i.R0'
    System::Call "Kernel32::GetProcessId(i R0) i.R3"
 
skip_pid_detection:
    System::Call 'Kernel32::CreateToolhelp32Snapshot(i ${PROCESSINFO.TH32CS_SNAPPROCESS},i R3) i.R0'
 
    IntCmp $R0 ${PROCESSINFO.INVALID_HANDLE_VALUE} end ;someting wrong
 
    ;$R9=PROCESSENTRY32
    ;typedef struct tagPROCESSENTRY32 {
    ;  DWORD     dwSize;
    ;  DWORD     cntUsage;
    ;  DWORD     th32ProcessID;
    ;  ULONG_PTR th32DefaultHeapID;
    ;  DWORD     th32ModuleID;
    ;  DWORD     cntThreads;
    ;  DWORD     th32ParentProcessID;
    ;  LONG      pcPriClassBase;
    ;  DWORD     dwFlags;
    ;  TCHAR     szExeFile[MAX_PATH];
    ;}PROCESSENTRY32, *PPROCESSENTRY32;
    ;dwSize=4*9+260
 
    System::Alloc 1024
    pop $R9
    System::Call "*$R9(i 296)"
 
    System::Call 'Kernel32::Process32First(i R0, i $R9) i.R1'
    StrCmp $R1 0 end
 
nnext_iteration:
    System::Call "*$R9(i,i,i.R1)" ;get PID
    IntCmp $R1 $R3 exitloop
 
    System::Call 'Kernel32::Process32Next(i R0, i $R9) i.R1'
    IntCmp $R1 0 0 nnext_iteration nnext_iteration
 
exitloop:
    ;$0 - pid
    ;$1 - threads
    ;$2 - ppid
    ;$3 - priority
    ;$4 - process name
    System::Call "*$R9(i,i,i.r0,i,i,i.r1,i.r2,i.r3,i,&t256.r4)" ; Get next module
 
    ;free:
    System::Free $R9
    System::Call "Kernel32::CloseToolhelp32Snapshot(i R0)"
 
    ;===============
    ;now get full path and commandline
 
    System::Call "Kernel32::OpenProcess(i 1040, i 0, i r0)i .R0"
 
    StrCmp $R0 0 end
 
    IntOp $R8 0 + 256
    System::Call "psapi::GetModuleFileNameEx(i R0,i 0,t .r5, *i $R8)i .R1"
 
end:
    Pop $R8
    Pop $R9
    Pop $R1
    Pop $R0
    Exch $5
    Exch 1
    Exch $4
    Exch 2  
    Exch $3
    Exch 3
    Exch $2
    Exch 4
    Pop $1
    Exch 4
    Exch $0
    Exch 5  
    Pop $R3
!macroend ;FUNC_GETPROCESSINFO
 
Function _GetProcessInfo
    !insertmacro FUNC_GETPROCESSINFO
FunctionEnd
 
Function un._GetProcessInfo
    !insertmacro FUNC_GETPROCESSINFO
FunctionEnd
 
!endif ;GETPROCESSINFO_INCLUDED

Version for Unicode NSIS

; NSIS PROCESS INFO LIBRARY - GetProcessInfo.nsh
; Version 1.1 - Mar 28th, 2011
;
; Description:
;   Gets process information.
;
; Usage example:
;   ${GetProcessInfo} 0 $0 $1 $2 $3 $4
;   DetailPrint "pid=$0 parent_pid=$1 priority=$2 process_name=$3 exe=$4"
;
; History:
;   1.1 - 28/03/2011 - Added uninstall function, include guards, file header. Fixed getting full exe path on pre vista systems. (Sergius)
;
 
!ifndef GETPROCESSINFO_INCLUDED
!define GETPROCESSINFO_INCLUDED
 
!define PROCESSINFO.TH32CS_SNAPPROCESS      2
!define PROCESSINFO.INVALID_HANDLE_VALUE    -1
 
!define GetProcessInfo '!insertmacro GetProcessInfo'
 
;@in pid_in - if 0 - get current process info
;@out pid_out - real process id (may be useful, if pid_in=0)
;@out ppid - parent process id
;@out priority
;@out name - name of process
;@out fullname - fully-qualified path of process
!macro GetProcessInfo pid_in pid_out ppid priority name fullname
    Push ${pid_in}
    !ifdef __UNINSTALL__
        Call un._GetProcessInfo
    !else
        Call _GetProcessInfo
    !endif    
    ;name;pri;ppid;fname;pid;
    Pop ${name}
    Pop ${priority}
    Pop ${ppid}
    Pop ${fullname}
    Pop ${pid_out}
!macroend
 
!macro FUNC_GETPROCESSINFO
    Exch $R3 ;pid
    Push $0
    Push $1
    Push $2
    Push $3
    Push $4
    Push $5
    Push $R0 ;hSnapshot
    Push $R1 ;result
    Push $R9 ;PROCESSENTRY32;MODULEENTRY32 and so on
    Push $R8
 
    ;zero registers to waste trash, if error occurred
    StrCpy $0 ""
    StrCpy $1 ""
    StrCpy $2 ""
    StrCpy $3 ""
    StrCpy $4 ""
    StrCpy $5 ""
 
    IntCmp $R3 0 0 skip_pid_detection skip_pid_detection
    System::Call 'kernel32::GetCurrentProcess() i.R0'
    System::Call "Kernel32::GetProcessId(i R0) i.R3"
 
skip_pid_detection:
    System::Call 'Kernel32::CreateToolhelp32Snapshot(i ${PROCESSINFO.TH32CS_SNAPPROCESS},i R3) i.R0'
 
    IntCmp $R0 ${PROCESSINFO.INVALID_HANDLE_VALUE} end ;someting wrong
 
    ;$R9=PROCESSENTRY32
    ;typedef struct tagPROCESSENTRY32 {
    ;  DWORD     dwSize;
    ;  DWORD     cntUsage;
    ;  DWORD     th32ProcessID;
    ;  ULONG_PTR th32DefaultHeapID;
    ;  DWORD     th32ModuleID;
    ;  DWORD     cntThreads;
    ;  DWORD     th32ParentProcessID;
    ;  LONG      pcPriClassBase;
    ;  DWORD     dwFlags;
    ;  TCHAR     szExeFile[MAX_PATH];
    ;}PROCESSENTRY32, *PPROCESSENTRY32;
    ;dwSize=4*9+2*260
 
    System::Alloc 1024
    pop $R9
    System::Call "*$R9(i 556)"
 
    System::Call 'Kernel32::Process32FirstW(i R0, i $R9) i.R1'
    StrCmp $R1 0 end
 
nnext_iteration:
    System::Call "*$R9(i,i,i.R1)" ;get PID
    IntCmp $R1 $R3 exitloop
 
    System::Call 'Kernel32::Process32NextW(i R0, i $R9) i.R1'
    IntCmp $R1 0 0 nnext_iteration nnext_iteration
 
exitloop:
    ;$0 - pid
    ;$1 - threads
    ;$2 - ppid
    ;$3 - priority
    ;$4 - process name
    System::Call "*$R9(i,i,i.r0,i,i,i.r1,i.r2,i.r3,i,&w256.r4)" ; Get next module
 
    ;free:
    System::Free $R9
    System::Call "Kernel32::CloseToolhelp32Snapshot(i R0)"
 
    ;===============
    ;now get full path and commandline
 
    System::Call "Kernel32::OpenProcess(i 1040, i 0, i r0)i .R0"
 
    StrCmp $R0 0 end
 
    IntOp $R8 0 + 256
    System::Call "psapi::GetModuleFileNameExW(i R0,i 0,t .r5, *i $R8)i .R1"
 
end:
    Pop $R8
    Pop $R9
    Pop $R1
    Pop $R0
    Exch $5
    Exch 1
    Exch $4
    Exch 2  
    Exch $3
    Exch 3
    Exch $2
    Exch 4
    Pop $1
    Exch 4
    Exch $0
    Exch 5  
    Pop $R3
!macroend ;FUNC_GETPROCESSINFO
 
Function _GetProcessInfo
    !insertmacro FUNC_GETPROCESSINFO
FunctionEnd
 
Function un._GetProcessInfo
    !insertmacro FUNC_GETPROCESSINFO
FunctionEnd
 
!endif ;GETPROCESSINFO_INCLUDED