Jump to content

Dllcall Psapi.dll Getprocessmemoryinfo


Recommended Posts

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
Link to comment
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

Link to comment
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!

Link to comment
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])
Edited by PerryRaptor
Link to comment
Share on other sites

  • Moderators

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])

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.

Link to comment
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.

Link to comment
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.

Link to comment
Share on other sites

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
Link to comment
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

Link to comment
Share on other sites

  • Moderators

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

-Livewire

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

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.

Link to comment
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?

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...