Invalid Handle error using PID from Process, Exist [Solved] Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
MrHue
Posts: 17
Joined: 01 Oct 2015, 02:51

Invalid Handle error using PID from Process, Exist [Solved]

17 Sep 2021, 06:31

I am trying to get some process info for my AHK script. However, the DllCalls return 0 and A_GetlastError is 6 (invalid handle).
What am I doing wrong please?

Code: Select all

	hProcess := DllCall("GetCurrentProcessId")	; returns same PID as Process, Exist
	, GuiObjects := DllCall("GetGuiResources", "Ptr", hProcess, "UInt", 1, "UInt")	; User objects: - WIN32 resources (accelerator tables, bitmap resources, dialog box templates, font resources, menu resources, raw data resources, string table entries, message table entries, cursors/icons) 
	, GDIObjects := DllCall("GetGuiResources", "Ptr", hProcess, "UInt", 0, "UInt")	; GDI objects: pens, brushes, fonts, palettes, regions, device contexts, bitmap headers) 
	, DllCall( "GetProcessHandleCount","Ptr", hProcess, "UIntP", nHandleCount)
	, DllCall( "QueryProcessCycleTime","Ptr", hProcess, "UInt64P", nCycleTime)
	Process, Exist
	msgbox % "PID " hProcess "/" ErrorLevel "`nHandles: " nHandleCount "`nCycle Time: " nCycleTime "`nUser Objects: " GuiObjects "`nGDI Objects: " GDIObjects "`nA_LastError: "  A_LastError
Dear jNizM, Thank you much!! (See post below for his answer)

The script below tests counting of GDI handles by creating and deleting DIBSections, and the number of GDI handles seems to be going up and down appropriately. The reason for using a function to create and delete DIBSections is to try manage GDI objects in one place so if the program suddenly exits, the GDI objects can still be freed using the OnExit procedure.

Code: Select all

#NoEnv

OnExit("ExitFunc")
global win_id
win_id := WinExist("A")


GDICount("Initial GDI handle count")
GDICount("Initial GDI handle count after using msgbox")
pbits1:=DIB("main1", hDC, dst, 31, 32)
GDICount("Handle count after call1")
pbits2:=DIB("main2", hDC2, dst2)
GDICount("Handle count after call2")
pbits3:=DIB("main1", hDC3, dst3)
GDICount("Handle count after call1 again")
pbits4:=DIB("main2", hDC4, dst4)
GDICount("Handle count after call2 again")

return

ExitFunc(ExitReason, ExitCode)
{
	GDICount("Before freeing GDI handles")
	DIB()
	GDICount("After freeing GDI handles")
	msgbox % ExitReason ": " ExitReason "`nExitCode: " ExitCode
}

GDICount(tip="")
{
	PID := DllCall("GetCurrentProcessId")
	, hProcess := DllCall("OpenProcess", "UInt", 0x0400, "char", 0, "Ptr", PID, "Ptr")	; PROCESS_QUERY_INFORMATION (0x0400)
	, GuiObjects := DllCall("GetGuiResources", "Ptr", hProcess, "UInt", 1, "UInt")	; User objects: - WIN32 resources (accelerator tables, bitmap resources, dialog box templates, font resources, menu resources, raw data resources, string table entries, message table entries, cursors/icons) 
	, GDIObjects := DllCall("GetGuiResources", "Ptr", hProcess, "UInt", 0, "UInt")	; GDI objects: pens, brushes, fonts, palettes, regions, device contexts, bitmap headers) 
	, DllCall( "GetProcessHandleCount","Ptr", hProcess, "UIntP", nHandleCount)
	, DllCall( "QueryProcessCycleTime","Ptr", hProcess, "UInt64P", nCycleTime)
	, DllCall("CloseHandle", "Ptr", hProcess)
	msgbox % tip "`nPID " hProcess "`nHandles: " nHandleCount "`nCycle Time: " nCycleTime "`nUser Objects: " GuiObjects "`nGDI Objects: " GDIObjects "`nA_LastError: "  A_LastError
}

DIB(FuncID:="", byref hDC:="", byref dst:="", w:=1, h:=1)	; return pbits pointer to bitmap
{
	static DIBs:={}, INFO
	if !INFO		; initialize bitmap info STRUCTURE
		VarSetCapacity(INFO, 40, 0)
		, NumPut(32, NumPut(1, NumPut(-h, NumPut(w, NumPut(40, INFO, 0, "uint"), "int"), "int"), "UShort"), 0, "UShort") ; bitmap info for CreateDIB (40 bytes), negative height for top down search
	if !FuncID		; free all
	{
		for id in DIBs
		{
			if DIBS[id].memDC
				DllCall("DeleteDC", "ptr", DIBS[id].memDC)
				, DllCall("DeleteObject", "ptr", DIBS[id].dib)
			if DIBS[id].winDC
				DllCall("ReleaseDC", "ptr", win_id, "ptr", DIBS[id].winDC)
		}
		DIBs:={}
	}
	else if IsByRef(hDC)
	{
		if !DIBs[FuncID].Count() {
			DIBs[FuncID]:={}
			, DIBs[FuncID].w:=w
			, DIBs[FuncID].h:=h
			, hDC := DIBs[FuncID].winDC := DllCall("user32.dll\GetDCEx", "Ptr", win_id, "Ptr", 0, "UInt", 3, "Ptr")
			if IsByRef(dst)
			{
				NumPut(-h, NumPut(w, INFO, 4, "int"), "int")	; bitmap info for CreateDIB (40 bytes), negative height for top down search
				, dst := DIBs[FuncID].memDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "Ptr")
				, DIBs[FuncID].dib  := DllCall("CreateDIBSection", "Ptr", dst, "Ptr", &INFO, "UInt", 0, "Ptr*", pbits, "Ptr", 0, "UInt", 0, "Ptr")
				, DllCall("SelectObject", "Ptr", dst, "Ptr", DIBs[FuncID].dib, "Ptr")
				return DIBs[FuncID].pbits := pbits
			}
		} else if (DIBs[FuncID].w==w) && (DIBs[FuncID].h==h) && DIBs[FuncID].memDC { ; use old DIB if possible
			hDC := DIBs[FuncID].winDC 
			, dst := DIBs[FuncID].memDC
			return DIBs[FuncID].pbits
		} else {						; recreate DIB if w or h is different from before
			DIB(FuncID)
			return DIB(FuncID, hDC, dst, w, h)
		}
	}
	else if DIBs[FuncID].Count()
        {
		if DIBS[FuncID].memDC
			DllCall("DeleteDC", "ptr", DIBS[FuncID].memDC)
			, DllCall("DeleteObject", "ptr", DIBS[FuncID].dib)
		DllCall("ReleaseDC", "ptr", win_id, "ptr", DIBS[FuncID].winDC)
		, DIBs.Delete(FuncID)
	}
}
Last edited by MrHue on 17 Sep 2021, 07:31, edited 7 times in total.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Invalid Handle error using PID from Process, Exist  Topic is solved

17 Sep 2021, 06:42

GetGuiResources -> The handle must refer to a process in the current session, and must have the PROCESS_QUERY_INFORMATION access right
GetProcessHandleCount -> The handle must have the PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access right.
QueryProcessCycleTime -> The handle must have the PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access right.

so you need to call OpenProcess first and at the end CloseHandle

Code: Select all

ProcessID := DllCall("kernel32\GetCurrentProcessId", "uint")
hProcess := DllCall("kernel32\OpenProcess", "uint", PROCESS_QUERY_INFORMATION := 0x0400, "int", 0, "uint", ProcessID, "ptr")
GR_USEROBJECTS := DllCall("user32\GetGuiResources", "ptr", hProcess, "uint", 1, "uint")
GR_GDIOBJECTS := DllCall("user32\GetGuiResources", "ptr", hProcess, "uint", 0, "uint")
DllCall("kernel32\GetProcessHandleCount", "ptr", hProcess, "uint*", HandleCount)
DllCall("kernel32\QueryProcessCycleTime", "ptr", hProcess, "uint64*", CycleTime)
DllCall("kernel32\CloseHandle", "ptr", hProcess)

MsgBox % "PID:`t`t" ProcessID "`nHandles:`t`t" HandleCount "`nCycle Time:`t" CycleTime "`nUSER objects:`t" GR_USEROBJECTS "`nGDI objects:`t" GR_GDIOBJECTS
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Invalid Handle error using PID from Process, Exist [Solved]

17 Sep 2021, 08:05

A bool is not a char (A BOOL is a 32-bit field that is set to 1 to indicate TRUE, or 0 to indicate FALSE.) -> Int
And the PID (ProcessID) is no Pointer / Handle (A DWORD is a 32-bit unsigned integer) -> UInt

Code: Select all

HANDLE OpenProcess(				-> Ptr
	DWORD dwDesiredAccess,		<- UInt
	BOOL  bInheritHandle,		<- Int
	DWORD dwProcessId			<- UInt
);
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: macromint, peter_ahk, Rauvagol, Spawnova, wineguy and 288 guests