Process
From Auto Hotkey
Process
Functions for performing the following operations on a process: check if it exists; change its priority; close it; wait for it to exist; wait for it to close.
OutputVar := ProcessExist(PID-or-Name)
Exist: Sets OutputVar to the Process ID (PID) if a matching process exists, or 0 otherwise. If the PID-or-Name parameter is blank, the script's own PID is retrieved.
OutputVar := ProcessClose(PID-or-Name)
Close: If a matching process is successfully terminated, OutputVar is set to its former Process ID (PID). Otherwise (there was no matching process or there was a problem terminating it), it is set to 0. Since the process will be abruptly terminated -- possibly interrupting its work at a critical point or resulting in the loss of unsaved data in its windows (if it has any) -- this method should be used only if a process cannot be closed by using WinClose on one of its windows.
ProcessSetPriority Priority , PID-or-Name
Priority: Changes the priority (as seen in Windows Task Manager) of the first matching process to Priority. If the PID-or-Name parameter is blank, the script's own priority will be changed.
Priority should be one of the following letters or words: L (or Low), B (or BelowNormal), N (or Normal), A (or AboveNormal), H (or High), R (or Realtime). Note: Any process not designed to run at Realtime priority might reduce system stability if set to that level.
The return value of this function is the Process ID (PID) of the process whose priority was set, or 0 if there is no matching process or there was a problem changing its priority.
OutputVar := ProcessWait(PID-or-Name , Timeout)
Wait: Waits up to Timeout seconds (can contain a decimal point) for a matching process to exist. If Timeout is omitted, the function will wait indefinitely. If a matching process is discovered, OutputVar is set to its Process ID (PID). If the function times out, OutputVar is set to 0.
OutputVar := ProcessWaitClose(PID-or-Name , Timeout)
WaitClose: Waits up to Timeout seconds (can contain a decimal point) for ALL matching processes to close. If Timeout is omitted, the function will wait indefinitely. If all matching processes are closed, OutputVar is set to 0. If the function times out, OutputVar is set to the Process ID (PID) of the first matching process that still exists.
Parameters
- OutputVar
The name of the variable in which to store the result, which is a Process ID (PID) or zero (0).
- PID-or-Name
This parameter can be either a number (the PID) or a process name as described below. It can also be left blank where indicated above.
PID: The Process ID, which is a number that uniquely identifies one specific process (this number is valid only during the lifetime of that process). The PID of a newly launched process can be determined via the Run function. Similarly, the PID of a window can be determined with WinGet. ProcessExist can also be used to discover a PID.
Name: The name of a process is usually the same as its executable (without path), e.g. notepad.exe or winword.exe. Since a name might match multiple running processes, only the first process will be operated upon. The name is not case sensitive.
Remarks
For Wait and WaitClose: Processes are checked every 100 milliseconds; the moment the condition is satisfied, the function stops waiting. In other words, rather than waiting for the timeout to expire, it immediately returns and continues execution of the script. Also, while the function is in a waiting state, new threads can be launched via hotkey, custom menu item, or timer.
Process list: Although there is no ProcessList function, the examples section demonstrates how to retrieve a list of processes via DllCall.
Related
Run, WinGet, WinClose, WinKill, WinWait, WinWaitClose, WinExist
Examples
; Example #1: Run "Notepad.exe", , , NewPID ProcessSetPriority "High", NewPID MsgBox "The newly launched notepad's PID is " NewPID
; Example #2:
NewPID := ProcessWait("Notepad.exe", 5.5)
if NewPID = 0
{
MsgBox "The specified process did not appear within 5.5 seconds."
return
}
; Otherwise:
MsgBox "A matching process has appeared (Process ID is " NewPID ")."
ProcessSetPriority "Low", NewPID
ProcessSetPriority "High" ; Have the script set itself to high priority.
WinClose "Untitled - Notepad"
ErrorLevel := ProcessWaitClose(NewPID, 5)
if ErrorLevel ; The PID still exists.
MsgBox "The process did not close within 5 seconds."
; Example #3: A hotkey to change the priority of the active window's process:
#z:: ; Win+Z hotkey
Gui := GuiCreate(, "Set Priority")
Gui.Add("Text",, "
(
Press ESCAPE to cancel, or double-click a new
priority level for the following window:
)")
Gui.Add("Text", "wp", WinGetTitle("A"))
LB := Gui.Add("ListBox", "r5", "Normal||High|Low|BelowNormal|AboveNormal")
SetPriority := Func("SetPriority").bind(LB, WinGetPID("A"))
LB.OnEvent("DoubleClick", SetPriority)
Gui.Add("Button", "default", "OK").OnEvent("Click", SetPriority)
Gui.OnEvent("Escape", "Gui_Close")
Gui.OnEvent("Close", "Gui_Close")
Gui.Show
return
SetPriority(LB, PID)
{
if ProcessSetPriority(LB.Text, PID)
MsgBox "Success: Its priority was changed to '" LB.Text "'."
else
MsgBox "Error: Its priority could not be changed to '" LB.Text "'."
WinClose
}
Gui_Close(Gui)
{
Gui.Destroy
}
; Example #4: Retrieves a list of running processes via DllCall then shows them in a MsgBox.
d := " | " ; string separator
s := 4096 ; size of buffers and arrays (4 KB)
ScriptPID := ProcessExist() ; The PID of this running script.
; Get the handle of this script with PROCESS_QUERY_INFORMATION (0x0400)
h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ScriptPID, "Ptr")
; Open an adjustable access token with this process (TOKEN_ADJUST_PRIVILEGES = 32)
DllCall("Advapi32.dll\OpenProcessToken", "Ptr", h, "UInt", 32, "PtrP", t)
VarSetCapacity(ti, 16, 0) ; structure of privileges
NumPut(1, ti, 0, "UInt") ; one entry in the privileges array...
; Retrieves the locally unique identifier of the debug privilege:
DllCall("Advapi32.dll\LookupPrivilegeValue", "Ptr", 0, "Str", "SeDebugPrivilege", "Int64P", luid)
NumPut(luid, ti, 4, "Int64")
NumPut(2, ti, 12, "UInt") ; enable this privilege: SE_PRIVILEGE_ENABLED = 2
; Update the privileges of this process with the new access token:
r := DllCall("Advapi32.dll\AdjustTokenPrivileges", "Ptr", t, "Int", false, "Ptr", &ti, "UInt", 0, "Ptr", 0, "Ptr", 0)
DllCall("CloseHandle", "Ptr", t) ; close this access token handle to save memory
DllCall("CloseHandle", "Ptr", h) ; close this process handle to save memory
hModule := DllCall("LoadLibrary", "Str", "Psapi.dll") ; increase performance by preloading the library
s := VarSetCapacity(a, s) ; an array that receives the list of process identifiers:
c := 0 ; counter for process idendifiers
DllCall("Psapi.dll\EnumProcesses", "Ptr", &a, "UInt", s, "UIntP", r)
Loop r // 4 ; parse array for identifiers as DWORDs (32 bits):
{
id := NumGet(a, A_Index * 4, "UInt")
; Open process with: PROCESS_VM_READ (0x0010) | PROCESS_QUERY_INFORMATION (0x0400)
h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id, "Ptr")
if !h
continue
VarSetCapacity(n, s, 0) ; a buffer that receives the base name of the module:
e := DllCall("Psapi.dll\GetModuleBaseName", "Ptr", h, "Ptr", 0, "Str", n, "UInt", s//2)
if !e ; fall-back method for 64-bit processes when in 32-bit mode:
if e := DllCall("Psapi.dll\GetProcessImageFileName", "Ptr", h, "Str", n, "UInt", s//2)
SplitPath n, n
DllCall("CloseHandle", "Ptr", h) ; close process handle to save memory
if (n && e) ; if image is not null add to list:
l .= n "`n", c++
}
DllCall("FreeLibrary", "Ptr", hModule) ; unload the library to free memory
;l := Sort(l) ; uncomment this line to sort the list alphabetically
MsgBox StrReplace(l, "`n", d), c " Processes", 0
; Example #5: Retrieves a list of running processes via COM.
Gui := GuiCreate(, "Process List")
LV := Gui.Add("ListView", "x2 y0 w400 h500", "Process Name|Command Line")
for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")
LV.Add("", process.Name, process.CommandLine)
Gui.Show
; Win32_Process: http://msdn.microsoft.com/en-us/library/aa394372.aspx