Sign in to follow this  
Followers 0
therks

Dllcall Psapi.dll Getprocessmemoryinfo

13 posts in this topic

#1 ·  Posted (edited)

I'm trying to rig up a GUI that could poll the running processes and give me the current memory usage of each, then give me the option of running the ReduceMemory UDF on whichever ones I choose.

So I've found this function on MSDN:

http://windowssdk.msdn.microsoft.com/libra...smemoryinfo.asp

It looks like what I need, but I've never been able to wrap my head around the DllStruct stuff. So far I've come up with this:

$pmc = DllStructCreate('dword;dword;int;int;int;int;int;int;int;int')
$pmcPtr = DllStructGetPtr($pmc)

$handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', @AUTOITPID)
$return = DllCall("paspi.dll", 'int', 'GetProcessMemoryInfo', 'long', $handle[0], 'ptr', $pmcPtr, 'long', DllStructGetSize($pmc))

if @error then
    msgbox(16,'error', 'error: ' & @error)
else
    msgbox(0,'success', 'huzzah')
endif

DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $handle[0])

But I keep getting error 2. If someone could get this working, I'd be very happy.

*Edit I had the third data type on the $return line set to dword, but DllCall doesn't support that type. I changed it to long, and now I get @error of 1 instead of 2.

Edited by Saunders

Share this post


Link to post
Share on other sites



I can't actually help you with this one. But I was wondering if you wouldn't mind posting this to scripts & scraps when you finish. This sounds like something I would like to use.

Also, you might want to somehow "protect" 4 critical system processes from having the ReduceMemory() function called on them. They are csrss, smss, winlogon, and lsass. Calling ReduceMemory() on any of these processes can cause system instability - hard freezes, blue screens, and reboots.

-John

Share this post


Link to post
Share on other sites

in your code

$return = DllCall("paspi.dll", 'int', 'GetProcessMemoryInfo', 'long', $handle[0], 'ptr', $pmcPtr, 'dword', DllStructGetSize($pmc))

why are u passing $handle[0] as 'long'? may be that's wat causing the error.


I believe we should all pay our tax with a smile. I tried - but they wanted cash!

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Added a MsgBox for troubleshooting; changed single quotes to double; put double quotes around False and 0x1f0fff...

$pmc = DllStructCreate("dword;dword;int;int;int;int;int;int;int;int")
$pmcPtr = DllStructGetPtr($pmc)

$handle = DllCall("kernel32.dll", "int", "OpenProcess", "int", "0x1f0fff", "int", "False", "int", @AUTOITPID)
$return = DllCall("paspi.dll", "int", "GetProcessMemoryInfo", "long", $handle[0], "ptr", $pmcPtr, "dword", DllStructGetSize($pmc))

MsgBox(0,"What We Got","pmc = " & $pmc & @CRLF & "pmcptr = " & $pmcptr & @CRLF & "handle > " & $handle & @CRLF & "Return < " & $return)

if @error then
    msgbox(16,"error", "error: " & @error)
else
    msgbox(0,"success", "huzzah")
endif

DllCall("kernel32.dll", "int", "CloseHandle", "int", $handle[0])
Edited by PerryRaptor

Share this post


Link to post
Share on other sites

Added a MsgBox for troubleshooting; changed single quotes to double; put double quotes around False and 0x1f0fff...

$pmc = DllStructCreate("dword;dword;int;int;int;int;int;int;int;int")
$pmcPtr = DllStructGetPtr($pmc)

$handle = DllCall("kernel32.dll", "int", "OpenProcess", "int", "0x1f0fff", "int", "False", "int", @AUTOITPID)
$return = DllCall("paspi.dll", "int", "GetProcessMemoryInfo", "long", $handle[0], "ptr", $pmcPtr, "dword", DllStructGetSize($pmc))

MsgBox(0,"What We Got","pmc = " & $pmc & @CRLF & "pmcptr = " & $pmcptr & @CRLF & "handle > " & $handle & @CRLF & "Return < " & $return)

if @error then
    msgbox(16,"error", "error: " & @error)
else
    msgbox(0,"success", "huzzah")
endif

DllCall("kernel32.dll", "int", "CloseHandle", "int", $handle[0])
It won't return an error because of the MsgBox()... same code, I just moved the Error handling to where it would need to be:
$pmc = DllStructCreate("dword;dword;int;int;int;int;int;int;int;int")
$pmcPtr = DllStructGetPtr($pmc)

$handle = DllCall("kernel32.dll", "int", "OpenProcess", "int", 0x1f0fff, "int", False, "int", @AUTOITPID)
$return = DllCall("paspi.dll", "int", "GetProcessMemoryInfo", "long", $handle[0], "ptr", $pmcPtr, "dword", DllStructGetSize($pmc))

if @error then
    msgbox(16,"error", "error: " & @error)
else
    msgbox(0,"success", "huzzah")
endif

MsgBox(0,"What We Got","pmc = " & $pmc & @CRLF & "pmcptr = " & $pmcptr & @CRLF & "handle > " & $handle & @CRLF & "Return < " & $return)


DllCall("kernel32.dll", "int", "CloseHandle", "int", $handle[0])

[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

Also, you might want to somehow "protect" 4 critical system processes from having the ReduceMemory() function called on them. They are csrss, smss, winlogon, and lsass. Calling ReduceMemory() on any of these processes can cause system instability - hard freezes, blue screens, and reboots.

Ooh, thanks, I didn't know about that. I had a quick script written up that just ran the function on everything that ProcessList gives me. No problems yet, but there could have been.

in your code

$return = DllCall("paspi.dll", 'int', 'GetProcessMemoryInfo', 'long', $handle[0], 'ptr', $pmcPtr, 'dword', DllStructGetSize($pmc))

why are u passing $handle[0] as 'long'? may be that's wat causing the error.

I got that idea from the ReduceMemory function, it passes a handle to the EmptyWorkingSet dllcall.

Added a MsgBox for troubleshooting; changed single quotes to double; put double quotes around False and 0x1f0fff...

Changing the single quotes to doubles doesn't do anything, it's just a preference. Putting quotes around the hex number and the False keyword turn them into strings, instead of leaving them as an integer and a keyword.

To see the difference, try this:

MsgBox(0, 'Test', 0xff & @LF & '0xff')

Thanks anyways though.

Share this post


Link to post
Share on other sites

I continue getting the error code 2 with your script. I've tinkered with it a bit today and looked at the help file. I guess the error 2 code from DLLCall() means it is an unknown returned type.

Looking at MSDN I can see the PSAPI GetProcessMemoryInfo; however, they talk about a return type Process_Memory_Counters {Ppsmemcounters} or Process_Memory_Counters_Ex.

I don't know much about this particular Win32 call, but what your seeking is interesting to say the least. It is much like a utility program that I have that allows me to assign affinity and allocate memory to applications. It would be nice to have a pure AutoIT replacement for Task Manager and the ability to adjust priority, set affinity, etc.

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Yes, I searched for Process_Memory_Counters, and found this:

The PROCESS_MEMORY_COUNTERS structure contains the memory statistics for a process.

typedef struct _PROCESS_MEMORY_COUNTERS {
  DWORD cb;
  DWORD PageFaultCount;
  SIZE_T PeakWorkingSetSize;
  SIZE_T WorkingSetSize;
  SIZE_T QuotaPeakPagedPoolUsage;
  SIZE_T QuotaPagedPoolUsage;
  SIZE_T QuotaPeakNonPagedPoolUsage;
  SIZE_T QuotaNonPagedPoolUsage;
  SIZE_T PagefileUsage;
  SIZE_T PeakPagefileUsage;
} PROCESS_MEMORY_COUNTERS, 
 *PPROCESS_MEMORY_COUNTERS;
From here: http://msdn.microsoft.com/library/default....ounters_str.asp

That's what lead me to create this line:

$pmc = DllStructCreate("dword;dword;int;int;int;int;int;int;int;int")

Perhaps the SIZE_T should be something else?

*Edit Just realized something, DllCall doesn't say you can have Dword as a data type, if you change it to 'int' then the error returned is 1. Doesn't really get me anywhere though...

Edited by Saunders

Share this post


Link to post
Share on other sites

Anybody who knows what they're doing that can weigh in on this topic?

Share this post


Link to post
Share on other sites

I was thinking of making the same thing but never got around to it...you may want to look at this. This is not using psapi though.

$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$colItems = ""
$strComputer = "localhost"

$Output=""
$Output = $Output & "Computer: " & $strComputer  & @CRLF
$Output = $Output & "==========================================" & @CRLF
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
$colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", _
                                          $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

If IsObj($colItems) then
   For $objItem In $colItems
      $Output = $Output & "Name: " & $objItem.Name & @CRLF
      $Output = $Output & "PageFileUsage: " & $objItem.PageFileUsage & @CRLF
      $Output = $Output & "PeakPageFileUsage: " & $objItem.PeakPageFileUsage & @CRLF
      $Output = $Output & "PeakVirtualSize: " & $objItem.PeakVirtualSize & @CRLF
      $Output = $Output & "PeakWorkingSetSize: " & $objItem.PeakWorkingSetSize & @CRLF
      $Output = $Output & "Priority: " & $objItem.Priority & @CRLF
      $Output = $Output & "PrivatePageCount: " & $objItem.PrivatePageCount & @CRLF
      $Output = $Output & "ProcessId: " & $objItem.ProcessId & @CRLF
      $Output = $Output & "QuotaNonPagedPoolUsage: " & $objItem.QuotaNonPagedPoolUsage & @CRLF
      $Output = $Output & "QuotaPagedPoolUsage: " & $objItem.QuotaPagedPoolUsage & @CRLF
      $Output = $Output & "QuotaPeakNonPagedPoolUsage: " & $objItem.QuotaPeakNonPagedPoolUsage & @CRLF
      $Output = $Output & "QuotaPeakPagedPoolUsage: " & $objItem.QuotaPeakPagedPoolUsage & @CRLF
      $Output = $Output & "WorkingSetSize: " & $objItem.WorkingSetSize & @CRLF

      if Msgbox(1,"WMI Output",$Output) = 2 then ExitLoop
      $Output=""
   Next
Else
   Msgbox(0,"WMI Output","No WMI Objects Found for class: " & "Win32_Process" )
Endif

Func WMIDateStringToDate($dtmDate)
    Return (StringMid($dtmDate, 5, 2) & "/" & _
    StringMid($dtmDate, 7, 2) & "/" & StringLeft($dtmDate, 4) _
    & " " & StringMid($dtmDate, 9, 2) & ":" & StringMid($dtmDate, 11, 2) & ":" & StringMid($dtmDate,13, 2))
EndFunc

** I just noticed you spelled psapi wrong in your script.

-Livewire

Share this post


Link to post
Share on other sites

...and we claim we can read...

Share this post


Link to post
Share on other sites

** I just noticed you spelled psapi wrong in your script.

-Livewire

That's funny, and now it returns success...

[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

** I just noticed you spelled psapi wrong in your script.

-Livewire

...and we claim we can read...

That's funny, and now it returns success...

Bahahahahhaa! Wow, I can't believe I missed that.

So now it's returning values, but only for processes running under my user profile. Any ideas how I can get the SYSTEM user's process information? Or even how I could figure out (through AutoIt) the user's of each process?

Share this post


Link to post
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
Sign in to follow this  
Followers 0