listing processes / recreating ProcessExist

Get help with using AutoHotkey and its commands and hotkeys
User avatar
jeeswg
Posts: 5442
Joined: 19 Dec 2016, 01:58
Location: UK

listing processes / recreating ProcessExist

20 Nov 2018, 18:21

tl;dr a documentation example can list all PIDs and process names (e.g. notepad.exe) (if admin mode is on), is this true also for the ProcessExist function (if so, how is this done in the source code, is this done with/without GetProcessImageFileName)

- This question is about 2 Winapi functions: GetProcessImageFileName and EnumProcessModules, and the AHK function ProcessExist (AHK v1: Process-Exist).
- I tried to translate the AHK source code (C++) for ProcessExist into AHK. It works, but fails to obtain the process names for around 75% of PIDs, this is fixed by using GetProcessImageFileName as a fallback (getting names for an extra 25% of PIDs, making around 50% of PIDs in total). However, AFAICS, the AHK function obtains all of those names without using GetProcessImageFileName.
- Also, the ProcessExist source code uses EnumProcessModules, but this appears to be redundant.
- I'm posting in case anyone can confirm whether the AHK source code is handling the 'GetProcessImageFileName' process names, and if so, how.

Code: Select all

;code based on:
;[EnumProcessModules approach:]
;ProcessExistNT4 (script_autoit.cpp)

;additional code using GetProcessImageFileName based on:
;[GetProcessImageFileName approach:]
;Process - Syntax & Usage | AutoHotkey
;https://autohotkey.com/docs/commands/Process.htm#ex4
;Retrieves a list of running processes via DllCall()

q:: ;list PIDs and process names
vDoEPM := 0 ;EnumProcessModules, appeared to make no difference
vDoGPIFM := 1 ;GetProcessImageFileName as a fallback, got more results

if !hModule := DllCall("kernel32\LoadLibrary", Str,"psapi.dll", Ptr)
	return
vSize := 4096
VarSetCapacity(vArrayPID, vSize)
vSize2 := 0
DllCall("psapi\EnumProcesses", Ptr,&vArrayPID, UInt,vSize, UIntP,vSize2)
vCount := 0
vOutput := ""
vTotal := vSize2 // 4
;MsgBox, % vTotal
Loop, % vSize2 // 4
{
	vPID := NumGet(&vArrayPID, A_Index*4-4, "UInt")
	;PROCESS_QUERY_INFORMATION := 0x400 ;PROCESS_VM_READ := 0x10
	if !hProc := DllCall("kernel32\OpenProcess", UInt,0x410, Int,0, UInt,vPID, Ptr)
	{
		vOutput .= "1`t" vPID "`t____`r`n"
		continue
	}

	if vDoEPM
	{
		VarSetCapacity(hMod, A_PtrSize, 0)
		VarSetCapacity(vSizeNeeded, vSize2, 0)
		NumPut(A_PtrSize, &vSizeNeeded, 0, "UInt")
		DllCall("psapi\EnumProcessModules", Ptr,hProc, Ptr,&hMod, UInt,A_PtrSize, Ptr,&vSizeNeeded)
		;MsgBox, % Format("0x{:X}", A_LastError) ;ERROR_PARTIAL_COPY := 0x12B
		hMod := NumGet(&hMod)
	}
	else
		hMod := 0

	vChars := 260
	VarSetCapacity(vPName, vChars*2, 0)
	if vRet := DllCall("psapi\GetModuleBaseName" (A_IsUnicode?"W":"A"), Ptr,hProc, Ptr,hMod, Str,vPName, UInt,vChars, UInt)
	{
		SplitPath, vPName, vPName
		vOutput .= "2`t" vPID "`t" vPName "`r`n"
		vCount++
	}

	;GetProcessImageFileName not mentioned in AHK source code
	if !vRet
	{
		if vDoGPIFM
		&& DllCall("psapi\GetProcessImageFileName", Ptr,hProc, Str,vPName, UInt,vChars, UInt)
		{
			SplitPath, vPName, vPName
			vCount++
		}
		vOutput .= "3`t" vPID "`t" vPName "`r`n"
		Process, Exist, % vPID
		vIsPID := ErrorLevel
		if !vIsPID
			MsgBox, % "ProcessExist failed: " vPID
	}
	DllCall("kernel32\CloseHandle", Ptr,hProc)
}
DllCall("kernel32\FreeLibrary", Ptr,hModule)
Clipboard := vCount "`r`n" vOutput
MsgBox, % vCount " / " vTotal "`r`n" vOutput
return
- Note: the example from the documentation, which uses GetProcessImageFileName and handles privileges, when run as admin, gives a complete list of process names.
Process - Syntax & Usage | AutoHotkey
https://autohotkey.com/docs/commands/Process.htm#ex4
Retrieves a list of running processes via DllCall()
- (Likewise Task Manager shows more process names when you run as admin by clicking 'Show processes from all users'.)

- Part of the reason I looked into this, was to see which techniques gave the most results.
- Both of these techniques appear to give the same lists in the same order: EnumProcesses (demonstrated above) and:
ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")

Return to “Ask For Help”

Who is online

Users browsing this forum: Bing [Bot], hasantr, JoeWinograd, medwatt, PadiFieldDojo, SorrymyEN, Unavailablename13 and 106 guests