<< Back to Script Library

Adjust Process Priority based on Session State

Adjusts the process priority in a users session based on its state.
Active = Normal
Idle / Disconnect = Process Priority Floor

Version: 1.5.8
Created: 2019-07-25
Modified: 2019-08-04
Creator: Trentent Tye
Downloads: 387
The Script Try this script with ControlUp Copy Script Copied to clipboard
        Adjusts the process priority based on session state. 

        Adjusts process priority for the session based on the session state.  Session state can be idle, disconnected or active.
        Idle is determined by a combination of Active + Idle time, whereas Active is determined when idle time = 0.

        Active will always equal 0 and any value above that means it's been idle and will cause the lowering of process priority

        . .SetProcessPriority.ps1 4 BOTTHEORYamttye Active 15 BelowNormal
        A session in the active state has been idle for 15 minutes, process priority will be adjusted down to BelowNormal

        . .SetProcessPriority.ps1 4 CONTROLUPtrententt Disconnected 0 Idle cmd/powershell
        A session in the disconnect state and process priority will be adjusted down to Idle, except for cmd.exe and powershell.exe

        . .SetProcessPriority.ps1 4 LABRATguyrleech Active 0 Idle
        A session is in a active state and process priority will be adjusted back to preconfigured values or Normal


        Created TTYE : 2019-07-25

    AUTHOR: Trentent Tye

Param (
    [Parameter(Mandatory=$true,HelpMessage='Session ID')][ValidateNotNullOrEmpty()]                                                                [int]$SessionID,
    [Parameter(Mandatory=$true,HelpMessage='Username in the format %DOMAIN%%username%')][ValidateNotNullOrEmpty()]                                [string]$UserName,
    [Parameter(Mandatory=$true,HelpMessage='Session State')][ValidateNotNullOrEmpty()][ValidateSet("Active","Disconnected")]                       [string]$SessionState,
    [Parameter(Mandatory=$true,HelpMessage='Idle Time (in minutes)')][ValidateNotNullOrEmpty()]                                                    [int]$IdleTime,
    [Parameter(Mandatory=$true,HelpMessage='Process Priority Floor')][ValidateSet("Normal","Idle","High","RealTime","BelowNormal","AboveNormal")]  [string]$Priority,
    [Parameter(Mandatory=$false,HelpMessage='Excluded Processes - without ".exe", and seperated by forward slash eg "cmd/winlogon/powershell"')]   [string]$ExcludedProcesses

Set-StrictMode -Version Latest
###$ErrorActionPreference = "Stop"

#Get Processes 
$VerbosePreference = "silentlycontinue"  #change to continue when you need to debug
[array]$processes = @(Get-Process | Where-Object {$_.SessionId -eq $SessionID} -ErrorAction SilentlyContinue)

#Get user sid
$sid = (New-Object System.Security.Principal.NTAccount($username)).Translate([System.Security.Principal.SecurityIdentifier]).value

#map HKU so we can access it
$null = New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS -ErrorAction SilentlyContinue

function Export-ProcessPriorityState ($ProcessList) {
    $sessionPriority = $ProcessList | Select-Object -Property ProcessName,Id,PriorityClass
    New-ItemProperty -Path "HKU:$sidVolatile Environment$sessionID" -PropertyType MultiString -Name ProcessPriorityState -Value ($sessionPriority | ConvertTo-Csv) -Force | Out-Null

if (-not(Test-Path "HKU:$sid")) {
    Write-Error -Message "Did not map the users hive, storing previous process priorities will not occur"

# borrowed Test-RegistryValue from the great https://www.jonathanmedd.net/2014/02/testing-for-the-presence-of-a-registry-key-and-value.html
function Test-RegistryValue {
    param (
    try {
        Get-ItemProperty -Path $Path | Select-Object -ExpandProperty $Value -ErrorAction Stop | Out-Null
        return $true
    catch {
        return $false

#if session is idle or in a disconnected state, lower process priority
if ((($SessionState -eq "Active") -and ($IdleTime -ge "1")) -or ($SessionState -eq "Disconnected")) {
    Write-Host "Found session in an idle or disconnected state.  Lowering processes in $sessionId to $priority"
    If (-not(Test-RegistryValue -Path "HKU:$sidVolatile Environment$sessionId" -value ProcessPriorityState)) { Export-ProcessPriorityState -ProcessList $processes }
    foreach ($process in $processes) {
        #skip lowering priority on excluded processes
        if (($excludedProcesses -split "/") -like "$($process.ProcessName)") {
            write-host "Excluded from process reprioritization: $($Process.ProcessName) - $($Process.Id)"
        } else {
            try {
                $Process.priorityclass = "$priority" #Ignore error output for some per-user processes that are controlled by the SYSTEM (csrss)
                Write-Verbose -Message "Reduced priority: $($Process.ProcessName) - $($Process.Id) - $($Process.priorityclass)"
            } catch {
                Write-Verbose -Message "Unable to reduce priority for  $($Process.ProcessName) - $($Process.Id)"

#Active Session -> Restore process priority
if (($SessionState -eq "Active") -and ($IdleTime -eq "0")) {
    Write-Host "Session $SessionId is an active state, adjusting process priorities to Normal"
    If (Test-RegistryValue -Path "HKU:$sidVolatile Environment$sessionId" -value ProcessPriorityState) {
        Write-Verbose -Message "Process History found"
        #retrieve previous values
        $previousProcessState = (Get-ItemProperty -Path "HKU:$sidVolatile Environment$sessionID").ProcessPriorityState | ConvertFrom-Csv #Get-ItemPropertyValue does not exist in PS2
        foreach ($process in $previousProcessState) {
            try {
                (Get-Process -Id ($process.Id) -ErrorAction SilentlyContinue).PriorityClass = "$($process.PriorityClass)"
                Write-Verbose -Message "Process priority: $($Process.ProcessName) - $($Process.Id) - $($Process.priorityclass)"
            } catch {
                Write-Verbose -Message "Unable to elevate priority for  $($Process.ProcessName) - $($Process.Id)"
        Remove-ItemProperty -Path "HKU:$sidVolatile Environment$sessionID" -Name ProcessPriorityState
    } else {
        #no process history so defaulting to set processes to normal priority
        Write-Verbose -Message "No Process History found"
        foreach ($process in $processes) { 
            try {
                (Get-Process -Id ($process.Id)).PriorityClass = "Normal"
                Write-Verbose -Message "Process priority: $($Process.ProcessName) - $($Process.Id) - $($Process.priorityclass)"
            } catch {
                Write-Verbose -Message "Unable to elevate priority for  $($Process.ProcessName) - $($Process.Id)"

Get Your Download Link

Gain access to ControlUp from your PC. Register and get a link to start your Free Trial.