Here is an example.
Code: Select all
#SingleInstance FORCE
#Persistent
SetWorkingDir %A_ScriptDir%
SetBatchLines, -1
SetTimer, DetectProcess, 10
return
DetectProcess:
If (processExist("NonexistentProcess.exe"))
msgbox Found the process.
return
processExist(Name){
Process,Exist,%Name%
return Errorlevel
}
Here is a solution I have adapted from the dllCall example in the help file
Code: Select all
#SingleInstance FORCE
#Persistent
SetWorkingDir %A_ScriptDir%
SetBatchLines, -1
SetTimer, DetectProcess, 10
return
DetectProcess:
If (processExist("NonexistentProcess.exe"))
msgbox Found the process.
return
ProcessExist(Name){
global HasPrivilege
If (HasPrivilege = 1){
l := ""
s := 4096
s := VarSetCapacity(a, s, 0)
DllCall("Psapi.dll\EnumProcesses", "Ptr", &a, "UInt", s, "UIntP", r)
sleep 10
Loop, % r // 4
{
id := NumGet(a, A_Index * 4, "UInt")
h := DllCall("OpenProcess", "UInt", 0x0010 | 0x0400, "Int", false, "UInt", id, "Ptr")
if !h
continue
VarSetCapacity(n, s, 0)
e := DllCall("Psapi.dll\GetModuleBaseName", "Ptr", h, "Ptr", 0, "Str", n, "UInt", A_IsUnicode ? s//2 : s)
if !e
if e := DllCall("Psapi.dll\GetProcessImageFileName", "Ptr", h, "Str", n, "UInt", A_IsUnicode ? s//2 : s)
SplitPath n, n
;DllCall("CloseHandle", "Ptr", h)
if (n && e)
if (n = Name)
return id
}
}
Else
SetDetectionPrivileges()
}
SetDetectionPrivileges(){
Process, Exist
h := DllCall("OpenProcess", "UInt", 0x0400, "Int", false, "UInt", ErrorLevel, "Ptr")
DllCall("Advapi32.dll\OpenProcessToken", "Ptr", h, "UInt", 32, "PtrP", t)
VarSetCapacity(ti, 16, 0)
NumPut(1, ti, 0, "UInt")
DllCall("Advapi32.dll\LookupPrivilegeValue", "Ptr", 0, "Str", "SeDebugPrivilege", "Int64P", luid)
NumPut(luid, ti, 4, "Int64")
NumPut(2, ti, 12, "UInt")
r := DllCall("Advapi32.dll\AdjustTokenPrivileges", "Ptr", t, "Int", false, "Ptr", &ti, "UInt", 0, "Ptr", 0, "Ptr", 0)
DllCall("CloseHandle", "Ptr", t)
DllCall("CloseHandle", "Ptr", h)
hModule := DllCall("LoadLibrary", "Str", "Psapi.dll")
global HasPrivilege := 1
return
}
Although soft page faults don't necessarily affect performance, I still think something is wrong with the Process,Exist function, at least on my system, considering the dllCall method is pretty much flawless in that regard. Maybe it has something to do with handles not being released, or being released too often?
Calling Process,Exist at a much slower rate such as 1000ms brings the page faults down to a reasonable level, however if I have a big list of processes (such as games) then I need to iterate quickly through them at the 10ms interval, checking whether each one exists, in order to execute some lines of code immediately on launch. So while a 1000ms loop might work fine for casual use, it's not a proper solution for advanced use.
Side question: are there are any windows API messages that are automatically sent whenever a new process is launched? In this case a loop would not be needed, saving a lot of CPU and other problems related to multiple threads running under the Timer scheme which can cause some problems such as thread deadlock when looping at faster speeds such as 10ms and sleeping within one of them, such as when waiting for a process to terminate.