Jump to content

SetProcessWorkingSetSizeEx and _WINAPI


joseLB
 Share

Recommended Posts

Hi

I need to change limits at some working sets in a server. For that, I found SetProcessWorkingSetSizeEx as the function to be used. -> http://msdn.microsoft.com/en-us/library/windows/desktop/ms686234(v=vs.85).aspx

At help I found _WinAPI_EmptyWorkingSet -> at include files (WinAPIProc.au3) I found a dll call to kernel 32. But this call has just 1 parameter:

(DllCall('kernel32.dll', 'handle', 'OpenProcess', 'dword', __Iif($__WINVER < 0x0600, 0x00000500, 0x00001100),    'bool', 0, 'dword', $iPID))

(DllCall(@SystemDir & 'psapi.dll', 'bool', 'EmptyWorkingSet', 'handle', $hProcess[0]))

And, for SetProcessWorkingSetSizeEx there are 3 (or 4) parameters.

I have no idea on how to call kernel32 with these 3/4 parameters.... :sweating:

Any help?

Thanks

Jose

Link to comment
Share on other sites

https://www.autoitscript.com/autoit3/docs/functions/DllCall.htm

DllCall("Kernel32.dll",,"SetProcessWorkingSetSize")

I've never used it but this is what I've seen in the forums over the years.

Get Scite to add a popup when you use a 3rd party UDF -> http://www.autoitscript.com/autoit3/scite/docs/SciTE4AutoIt3/user-calltip-manager.html

Link to comment
Share on other sites

https://www.autoitscript.com/autoit3/docs/functions/DllCall.htm

DllCall("Kernel32.dll",,"SetProcessWorkingSetSize")

I've never used it but this is what I've seen in the forums over the years.

Thanks computergroove, I´m trying to figure out how to do it, DLL call seems to be not so complex.

But at    we can see 2 dll calls, you know the reason?

And at

 Local $hProcess = DllCall('kernel32.dll', 'handle', 'OpenProcess', 
'dword', __Iif($__WINVER < 0x0600, 0x00000500, 0x00001100), 
_   'bool', 0, 'dword', $iPID)
 
 If @error Or Not $hProcess[0] Then Return SetError(@error + 20, 
@extended, 0)
 
 
 Local $aRet = DllCall(@SystemDir & '\psapi.dll', 'bool', 
'EmptyWorkingSet', 'handle', $hProcess[0])
 
 If __CheckErrorCloseHandle($aRet, $hProcess[0]) Then Return 
SetError(@error, @extended, 0)

And here  we can see something more like to be the thing to be done:

Func _WinAPI_AssignProcessToJobObject($hJob, $hProcess)
 Local $aRet = DllCall('kernel32.dll', 'bool', 
'AssignProcessToJobObject', 'handle', $hJob, 'handle', $hProcess)....

 

Edited by joseLB
Link to comment
Share on other sites

Thanks Danyfirex

I tried:

Global Const $QUOTA_LIMITS_HARDWS_MIN_DISABLE=0x00000002 , $QUOTA_LIMITS_HARDWS_MAX_DISABLE=0x00000008
Global Const $QUOTA_LIMITS_HARDWS_MIN_ENABLE=0x00000001,   $QUOTA_LIMITS_HARDWS_MAX_ENABLE=0x00000004
Func _WINAPI_SetProcessWorkingSetSizeEx($iPID = 0, $dwMinimumWorkingSetSize=2000, $dwMaximumWorkingSetSize=4000, $iFlags= $QUOTA_LIMITS_HARDWS_MAX_DISABLE)
 If Not $iPID Then $iPID = @AutoItPID

 Local $aRet = DllCall('kernel32.dll','int', 'SetProcessWorkingSetSizeEx', _
       'long', $iPID, _
       'long', $dwMinimumWorkingSetSize, _
       'long', $dwMaximumWorkingSetSize, _
       'long', $iFlags)

 If @error Then Return SetError(@error, @extended, False)
 ; If Not $aRet[0] Then Return SetError(1000, 0, 0)

 Return $aRet[0]
EndFunc

...

$erro= _WINAPI_SetProcessWorkingSetSizeEx(0,5000000,7000000, $QUOTA_LIMITS_HARDWS_MIN_ENABLE)
MsgBox(1,"E="&$erro,@error)

==> return is $erro=0,@error=0 and limits are not set.

====> so, I added _arrayDisplay ($aRet) just after  DLLCal and has this result, that seems to be the parameters I gave at the call:

[0]|0
[1]|6212
[2]|5000000
[3]|7000000
[4]|1

===> i also tried to fix values  at dll cal, for example flags= 4+1 = enable to not go up or down from stabilished limits. To force it to go out of limits I used arrays of 100.000 integers looping and ading values to cells and so on. At task manager it goes up and down the limits, that is, the call has no efect.

At mdsn, "The handle must have PROCESS_SET_QUOTA access rights". => I´m administrator of my Noteboook, so I have no idea if this could be the problem or bad call/prameters passing.

Edited by joseLB
Link to comment
Share on other sites

Try this:

; Johnmcloud - 2014

Local $sInfo = _GetWorkingSetSize()
MsgBox("", "Before", $sInfo)

_WinAPI_SetProcessWorkingSetSizeEx(0, 50*1024*1024, 100*1024*1024)
If @error Then Exit MsgBox("", "", @error)
Sleep(1000)

;~ If both dwMinimumWorkingSetSize and dwMaximumWorkingSetSize have the value –1, the function removes as many pages as possible from the working set of the specified process.
;~ _WinAPI_SetProcessWorkingSetSizeEx()

Local $sInfo = _GetWorkingSetSize()
MsgBox("", "After", $sInfo)

Func _WinAPI_SetProcessWorkingSetSizeEx($iPID = 0, $dwMinimumWorkingSetSize = -1, $dwMaximumWorkingSetSize = -1, $iFlags = 5)
    ; http://msdn.microsoft.com/en-us/library/windows/desktop/ms686237(v=vs.85).aspx
    ; Flags = QUOTA_LIMITS_HARDWS_MAX_ENABLE + QUOTA_LIMITS_HARDWS_MIN_ENABLE
    If @OSBuild <= 2600 Then Return SetError(1, 0, 0) ; Minimum supported client Windows Vista
    If Not $iPID Then $iPID = @AutoItPID
    Local Const $PROCESS_SET_QUOTA = 0x00000100
    Local $aHWnd = DllCall('kernel32.dll', 'int', 'OpenProcess', 'int', $PROCESS_SET_QUOTA, 'int', 1, 'int', $iPID)
    If @error Then Return SetError(2, 0, 0)
    DllCall('kernel32.dll', 'int', 'SetProcessWorkingSetSizeEx', 'int', $aHWnd[0], 'int', $dwMinimumWorkingSetSize, 'int', $dwMaximumWorkingSetSize, 'int', $iFlags)
    If @error Then Return SetError(3, 0, 0)
    DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $aHWnd[0])
    Return 1
EndFunc   ;==>_WinAPI_SetProcessWorkingSetSizeEx

Func _GetWorkingSetSize($iPID = 0) ; By Johnmcloud
    If Not $iPID Then $iPID = @AutoItPID
    Local $aProcessList = ProcessList(), $ProcessName = "", $Output = ""
    For $i = 1 To $aProcessList[0][0]
        If $aProcessList[$i][1] = $iPID Then
            $ProcessName = $aProcessList[$i][0]
            ExitLoop
        EndIf
    Next
    If $ProcessName = "" Then Return SetError(1, 0, 0)
    $objWMIService = ObjGet("winmgmts:\\" & "localhost" & "\root\CIMV2")
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name = '" & $ProcessName & "'", "WQL", 0x10 + 0x20)
    If IsObj($colItems) Then
        For $objItem In $colItems
            $Output &= "Caption: " & $objItem.Caption & @CRLF
            $Output &= "MaximumWorkingSetSize: " & $objItem.MaximumWorkingSetSize & @CRLF
            $Output &= "MinimumWorkingSetSize: " & $objItem.MinimumWorkingSetSize & @CRLF
        Next
        Return $Output
    Else
        Return SetError(1, 0, 0)
    EndIf
EndFunc   ;==>_GetWorkingSetSize
Edited by johnmcloud
Link to comment
Share on other sites

Hi John, thnak you a lot.

 We (you) are almost there. Follows my entire code using your UDF. 

As supposed my udf did nothing with ws sizes...

Yours, at the end of UDF call, decreases ws abruptely, that is a good signal, something is working. But as you can see, it still don´t respect the limits imposed.

The program is just some thing to force WS to increase and decrease, with a bunch of msgbox to stop/follow each step.

Task manager must opened, looking at AutoIt3.exe ws size.

(I´m testing in a win7 notebook)

#include <Array.au3>
Global Const $QUOTA_LIMITS_HARDWS_MIN_DISABLE=0x00000002 , $QUOTA_LIMITS_HARDWS_MAX_DISABLE=0x00000008
Global Const $QUOTA_LIMITS_HARDWS_MIN_ENABLE=0x00000001,   $QUOTA_LIMITS_HARDWS_MAX_ENABLE=0x00000004
; Johnmcloud - 2014

;_WinAPI_SetProcessWorkingSetSizeEx()
;If @error Then Exit MsgBox("", "", @error)
;Sleep(10000)

Func _WinAPI_SetProcessWorkingSetSizeEx($iPID = 0, $dwMinimumWorkingSetSize = -1, $dwMaximumWorkingSetSize = -1, $iFlags = 5)
    ; http://msdn.microsoft.com/en-us/library/windows/desktop/ms686237(v=vs.85).aspx
    ; $iFlags = $QUOTA_LIMITS_HARDWS_MAX_ENABLE + $QUOTA_LIMITS_HARDWS_MIN_ENABLE
    If @OSBuild <= 2600 Then Return SetError(1, 0, 0) ; Minimum supported client Windows Vista
    If Not $iPID Then $iPID = @AutoItPID
    Local Const $PROCESS_ALL_ACCESS = 0x1F0FFF ; MSDN say to use PROCESS_SET_QUOTA
    Local $aHWnd = DllCall('kernel32.dll', 'int', 'OpenProcess', 'int', $PROCESS_ALL_ACCESS, 'int', 1, 'int', $iPID)
    If @error Then Return SetError(2, 0, 0)
    DllCall('kernel32.dll', 'int', 'SetProcessWorkingSetSizeEx', 'int', $aHWnd[0], 'int', $dwMinimumWorkingSetSize, 'int', $dwMaximumWorkingSetSize, 'int', $iFlags)
    If @error Then Return SetError(3, 0, 0)
    DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $aHWnd[0])
    DllClose('kernel32.dll')
MsgBox(0,"udf End","minWS="&$dwMinimumWorkingSetSize &@cr& "maxWS="&$dwMaximumWorkingSetSize)
    Return 1
EndFunc   ;==>_WinAPI_SetProcessWorkingSetSizeEx



Global $x[150000]
MsgBox(0,1,"small WS")
for $k=1 to 150000-1
    $x[$k]=$k
Next

MsgBox(1,2,"medium WS - 150K cells populated")
_WINAPI_SetProcessWorkingSetSizeEx(0,4500000,5000000)
MsgBox(1,2,"after UDF call - error=" & @error)

Global $y[150000]
for $k=1 to 150000-1
    $y[$k]=$k
Next
MsgBox(0,3,"Larger WS -> 2nd array=> + 150K populated")

Global $x=0
MsgBox(0,4,"1st array destroyed => medium WS")

Global $y=0
MsgBox(0,5,"2st array destroyed => small WS")
Edited by joseLB
Link to comment
Share on other sites

  • Moderators
The return types are not pointers for your: $dwMinimumWorkingSetSize and $dwMaximumWorkingSetSize.
So your values won't change from what you sent into the function... Unsure why you have the MsgBox() checking them is why I state this.
 
And other than this:
DllCall('kernel32.dll', 'int', 'SetProcessWorkingSetSizeEx', 'int', $aHWnd[0], 'int', $dwMinimumWorkingSetSize, 'int', $dwMaximumWorkingSetSize, 'int', $iFlags)
Should probably be more like:
DllCall('kernel32.dll', 'int', 'SetProcessWorkingSetSizeEx', 'handle', $aHWnd[0], 'dword', $dwMinimumWorkingSetSize, 'dword', $dwMaximumWorkingSetSize, 'int', $iFlags)
 
I would say that your main issue may be your level of process privilege even as admin.
 
Try maybe using the _EnableDebugPrivilege() func from here that I wrote.
 
And running your function call after for the setting size.

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

SmOke_N i'm not an expert of DllCall, is exactly the opposite :D

But my function work with all the 'int' parameter, i have edited the code with an example because seems joseLB don't have understood how SetProcessWorkingSetSizeEx work

Before
Caption: Autoit3.exe
MaximumWorkingSetSize: 1380
MinimumWorkingSetSize: 200
After
Caption: Autoit3.exe 
MaximumWorkingSetSize: 102400 
MinimumWorkingSetSize: 51200





But if you think your version of SetProcessWorkingSetSizeEx is more "correct", i'll edit it is not a problem.

Edited by johnmcloud
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...