Jump to content

DllCall --> GetGuiResources returns bad/empty data?


L00py
 Share

Recommended Posts

Hi all. Quick question for someone more knowledgeable in Win32 API calls. I have the following code:

$hProcess = ProcessExists("explorer.exe")
$GDIcount = DllCall("user32.dll", "int", "GetGuiResources", "hwnd", $hProcess, "int", 0)
_ArrayDisplay($GDIcount, "test")

Now, what I expect to happen is that this call returns an INT with the number of GDI Objects in use by the specified process. The array I get returned has the correct PID but the return value in $GDICount[0] is always zero. When I look at the example programs built in other languages, they work as expected in that the return value is the same as the GDI Objects column's value in Task Manager. I have tried using different data types for the $hProcess parameter in the DllCall above, including ptr and int with no change in return values. I tried the same data type changes to the 2nd parameter with no changes either.

Does anyone have a suggestion as to why this particular function does not return what I expect? I did try using the MessageBox example from the DllCall help page example and it worked as expected.

Thanks for your time!

Cheers,

L00py

Link to comment
Share on other sites

ProcessExists() returns process ID.

GetGuiResources requires handle. To get handle, DllCall OpenProcess (as dwDesiredAccess specify PROCESS_QUERY_INFORMATION, bInheritHandle - 0, and dwProcessId - what you get from ProcessExists). Then pass this handle to your GetGuiResources. DllCall CloseHandle when you don't need it, just to be nice.

Edited by Siao

"be smart, drink your wine"

Link to comment
Share on other sites

ProcessExists() returns process ID.

GetGuiResources requires handle. To get handle, DllCall OpenProcess (as dwDesiredAccess specify PROCESS_QUERY_INFORMATION, bInheritHandle - 0, and dwProcessId - what you get from ProcessExists). Then pass this handle to your GetGuiResources. DllCall CloseHandle when you don't need it, just to be nice.

Heh, in all my searches yesterday, I didn't manage to hit on using OpenProcess to return that handle. :) Fixed and working now. Thanks!
Link to comment
Share on other sites

I could have used this a few weeks back when I was troubleshooting a GDI leak I resolved with a script

a little more convenient than process explorer

took OpenProcess call from _ReduceMemory() UDF by jftuga and wOuter

lazy mans process select - arraydisplay

select process from list

click 'Textselected'

click 'Close'

enjoy

Edit: fixed unclosed handles

Display GDI and USER handles for current process and selected process

#include <Array.au3>
#include <GUIConstants.au3>
#include <Process.au3>

;Global Const $PROCESS_ALL_ACCESS = 0x1f0fff
Global Const $PROCESS_QUERY_INFORMATION = 0x0400 ; comment out for v3.2.9.10 and up


; select single process from list then click 'TextSelected' button, then 'Close' (multiple selected items will be ignored)
$alist = ProcessList()
_ArraySort($aList, 0, 1, 0, 2, 0)
_ArrayDisplay($alist,"Select Process:  Click 'TextSelected', Then 'Close'",0,0)
$processname = StringSplit(ClipGet(), '|', 1)
ClipPut("")
Switch IsArray($processname)
    Case 1
        If UBound($processname) = 4 Then
            $processname = $processname[2]
        Else
            ContinueCase
        EndIf
    Case 0
        $processname = "explorer.exe"
Endswitch
$ai_GetProcessId = ProcessExists($processname)

GUICreate("User & GDI Handles To Objects Count",360,200,-1,-1,BitOR($WS_SYSMENU, $WS_CAPTION),$WS_EX_TOPMOST)
$label1 = GUICtrlCreateLabel("Process:",20,20,200,20)
$label2 = GUICtrlCreateLabel("GDI Objects:",20,40,120,20)
$label3 = GUICtrlCreateLabel("USER objects:",20,60,120,20)

$label4 = GUICtrlCreateLabel("Process:",20,100,320,20)
$label5 = GUICtrlCreateLabel("GDI Objects:",20,120,120,20)
$label6 = GUICtrlCreateLabel("USER objects:",20,140,120,20)

GUISetState (@SW_SHOW)

; used for current process, as script or compiled
$ai_GetCurrentProcessId = DllCall('kernel32.dll', 'int', 'GetCurrentProcessId')
$ai_GetCurrentProcessId = $ai_GetCurrentProcessId[0]
$ai_Handle1 = DllCall("kernel32.dll", 'hwnd', 'OpenProcess', 'dword', $PROCESS_QUERY_INFORMATION, 'dword', False, 'dword', $ai_GetCurrentProcessId)
If @error Then
    SetError(1)
    Exit
EndIf

; used for explorer.exe or any process - monitor your script for GDI handle leaks
;$ai_GetProcessId = ProcessExists($processname[2]) ; enter your script exe name
$ai_Handle2 = DllCall("kernel32.dll", 'hwnd', 'OpenProcess', 'dword', $PROCESS_QUERY_INFORMATION, 'dword', False, 'dword', $ai_GetProcessId)
If @error Then
    SetError(1)
    Exit
EndIf

$timer = TimerInit()
While 1
    $msg = GUIGetMsg()
    If TimerDiff($timer) >= 250 Then
        $GDIcount1 = DllCall("user32.dll", "int", "GetGuiResources", "hwnd", $ai_Handle1[0], "int", 0)
        $USERcount1 = DllCall("user32.dll", "int", "GetGuiResources", "hwnd", $ai_Handle1[0], "int", 1)
        $GDIcount2 = DllCall("user32.dll", "int", "GetGuiResources", "hwnd", $ai_Handle2[0], "int", 0)
        $USERcount2 = DllCall("user32.dll", "int", "GetGuiResources", "hwnd", $ai_Handle2[0], "int", 1)
        GUICtrlSetData($label1, "Process:"&@TAB&_ProcessGetName($ai_GetCurrentProcessId)&" ") ; 'AutoIt3.exe' if run as script
        GUICtrlSetData($label2, "GDI Objects:"&@TAB&$GDIcount1[0])
        GUICtrlSetData($label3, "USER objects:"&@TAB&$USERcount1[0])
        GUICtrlSetData($label4, "Process:"&@TAB&_ProcessGetName($ai_GetProcessId))
        GUICtrlSetData($label5, "GDI Objects:"&@TAB&$GDIcount2[0])
        GUICtrlSetData($label6, "USER objects:"&@TAB&$USERcount2[0])
        $timer = TimerInit()
    Endif
    If $msg = $GUI_EVENT_CLOSE Then Exit
Wend

Func OnAutoItExit()
    DllCall('kernel32.dll', 'int', 'CloseHandle', 'hwnd', $ai_Handle1[0])
    DllCall('kernel32.dll', 'int', 'CloseHandle', 'hwnd', $ai_Handle2[0])
    Beep(1000,5)
EndFunc
Edited by rover

I see fascists...

Link to comment
Share on other sites

script is not closing handles, even with int changed to hwnd....

closehandle call returning zero

according to MSDN should be 'Non-zero'

MSDN - Close Handle

$ret1 = DllCall('kernel32.dll', 'int', 'CloseHandle', 'hwnd', $ai_Handle1)

ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ret1[0] = ' & $ret1[0] & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

@@ Debug(85) : $ret1[0] = 0

Edited by rover

I see fascists...

Link to comment
Share on other sites

$ai_Handle1 is an array

Thanks Picasso, for the extra set of eyes (and brain)

missed that, even though I had used $ai_Handle1[0] in the GuiResource call

sometimes can't see the trees for the forest...

btw, my vote for best CatHead Avatar on the forum

Thanks

I see fascists...

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...