Sign in to follow this  
Followers 0
joseLB

SetProcessWorkingSetSizeEx and _WINAPI

11 posts in this topic

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

Share this post


Link to post
Share on other sites



#3 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites

 

venezuela.png Would you like to say thank to Danyfirex using a warmy way?  offer me a cup of coffee... coffee.png

autoit_scripter_blue_userbar.png

       AutoIt...

 

 

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

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
1 person likes this

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites
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.

[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

#9 ·  Posted (edited)

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

Share this post


Link to post
Share on other sites

Actually i'm using PROCESS_SET_QUOTA like MSDN link, yesterday was ALL_ACCESS, not today :D

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