Jump to content

Set Process Affinity


Recommended Posts

I assume I can't post in that particular section of the forum because I'm a n00b (ha!) so I'm gonna post it here and hope that a mod can drop-kick it where it belongs.

I did a bit of searching for folks asking about setting the affinity of a process in AutoIT, the last time I saw anyone mention it was way back in 2005. Even then, it was a cloudy mystery for anyone who wasn't sure about DLL calls.

Welp, thanks to the pieces of that thread, the MSDN knowledgebase, and a bit of peeking into some of the Include AU3's on how to properly do the calls, I have written a very simple SetProcessAffinity function to let you change the affinity of a given process tree. You'll need to know the PID of your process (easy if you're using the built-in AutoIT Run function) to make it work.

Here it is:

;; Function ProcessSetAffinity
;;
;; Inputs:
;;      iProcessID - the PID of the process to change affinity
;;      iProcessor - the integer value of the binary affinity bitmask (see below)
;;
;; Results:
;;    Returns -1 and sets @error = 1 if the process doesn't exist
;;      Returns -1 and sets @error = 2 if this script isn't able to get sufficient access to the process handle
;;      Returns 1 if the affinity was set to your request
;;      Returns 0 if the affinity could not be set
;; 
;; How Affinity Bitmasks Work:
;;
;; Bitmasks are a binary representation of what processor(s) a thread or process is allowed to run on
;; One binary digit per CPU, a zero means it -cannot- run on that CPU, a one means it -can- run on that CPU
;; So, if your machine has two processors:
;;
;; Binary   |  Integer  | Description
;; 01       =  1        =  Can run on the first CPU, but not the second
;; 10       =  2        =  Can run on the second CPU, but not the first
;; 11       =  3        =  Can run on the first and second CPU's
;;
;; If your machine had four processors:
;;
;; 0001     =  1        = Can run on the first CPU, but not the second, third or fourth
;; 0010     =  2        = Can run on the second CPU, but not the first, third or fourth
;; 0011     =  3        = Can run on the first and second CPU's, but not the third or fourth
;; 0100     =  4        = Can run on the third CPU, but not the first, second or fourth
;; 0101     =  5        = Can run on the first and third CPU's, but not the second or fourth
;; ... (continued ad-nauseum)

Func ProcessSetAffinity($iProcessID,$iProcessor = 1)
    Local $i_PID = ProcessExists($iProcessID)
    If Not $i_PID Then
        SetError(1)
        Return -1
    EndIf
    Local $hDLL = DllOpen('kernel32.dll')
    Local $aProcessHandle = DllCall($hDLL, 'int', 'OpenProcess', 'int', 0x0200, 'int', False, 'int', $i_PID)
    if $aProcessHandle[0] = 0 Then
        SetError(2)
        Return -1
    EndIf
    Local $aAffinity = DllCall($hDLL, 'int', 'SetProcessAffinityMask', 'int', $aProcessHandle[0], 'int', $iProcessor)
    DllCall($hDLL, 'int', 'CloseHandle', 'int', $aProcessHandle[0])
    DllClose($hDLL)
    Return $aAffinity[0]
EndFunc  ;==>ProcessSetAffinity

Hope someone gets use out of it :)

Link to comment
Share on other sites

;CPU0 and CPU1 selected - BinToDec(11)=3 result $affinity=3
;CPU0 selected - BinToDec(01) = 1 result $affinity=1
;CPU1 selected - BinToDec(10) = 2 result $affinity=2
;
;$action - 'Show'  return affinity state
;   - 'Set'   return affinity after modification
;
;Return = Process Mask / System Mask

MsgBox(0, '', ProcessAffinity('Show'))
MsgBox(0, '', ProcessAffinity('Set', 2))
MsgBox(0, '', ProcessAffinity('Set', 3))

Func ProcessAffinity($aaction, $affinity = '', $pid_process = @AutoItPID)
    Local $hprocess = DllCall("Kernel32.dll", "int", "OpenProcess", "int", 0x1F0FFF, "int", False, "int", $pid_process)
    Local $amask[3], $rbuffer, $psystem, $aresult, $pprocess, $iresult
    $rbuffer = DllStructCreate("int;int")
    $pprocess = DllStructGetPtr($rbuffer, 1)
    $psystem = DllStructGetPtr($rbuffer, 2)
    $aresult = DllCall("Kernel32.dll", "int", "GetProcessAffinityMask", "hwnd", $hprocess[0], "ptr", $pprocess, "ptr", $psystem)
    $amask[0] = $aresult[0] <> 0
    $amask[1] = DllStructGetData($rbuffer, 1)
    $amask[2] = DllStructGetData($rbuffer, 2)
    If $affinity - 0 = 0 Or $affinity > $amask[2] Then $affinity = $amask[2]
    Select
        Case $aaction = 'Show'
            DllCall("Kernel32.dll", "int", "CloseHandle", "int", $hprocess[0])
            Return $amask[1] & '/' & $amask[2]
        Case $aaction = 'Set'
            $iresult = DllCall("Kernel32.dll", "int", "SetProcessAffinityMask", "hwnd", $hprocess[0], "int", $affinity)
            $aresult = DllCall("Kernel32.dll", "int", "GetProcessAffinityMask", "hwnd", $hprocess[0], "ptr", $pprocess, "ptr", $psystem)
            $amask[1] = DllStructGetData($rbuffer, 1)
            $amask[2] = DllStructGetData($rbuffer, 2)
            DllCall("Kernel32.dll", "int", "CloseHandle", "int", $hprocess[0])
            Return $amask[1] & '/' & $amask[2]
    EndSelect
EndFunc   ;==>ProcessAffinity

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