4

There's this powershell script which can set processes' priorities from "Idle" to "Realtime" but some tools offer another priority level which drops a process's priority even below:

How to set that in Powershell?

Community
  • 1
  • 1
laggingreflex
  • 32,948
  • 35
  • 141
  • 196
  • The answer may be in one of the [other responses there](http://stackoverflow.com/a/675056/1324345) - look at the names of the priorities in the header of that code & note how at least one maps to the answer you found. Then try the others & look at the results. – alroc Feb 11 '14 at 12:27
  • No, I'm afraid it's not like that. First, because I did already test all those. And second, if you try to set the [priority from Windows task manager](http://i.imgur.com/PLuKrMW.png) itself, it doesn't provide that "background" option, which makes me believe that it isn't an option that goes along with all the other options of setting those different levels of priorities. It's definitely something different that sets some I/O/Memory priority, rather than process priority. – laggingreflex Feb 11 '14 at 13:39
  • [Here is a SO question on how to do it in C#](http://stackoverflow.com/questions/301290/how-can-i-o-priority-of-a-process-be-increased), perhaps you can port the answer of that question to Powershell and post your own answer showing others. – Scott Chamberlain Jun 04 '14 at 22:43
  • There's a free program called Process Hacker (similar to Process Explorer) that will let you set the IO priority separately from the CPU priority. https://github.com/processhacker/processhacker – Brain2000 Jan 27 '19 at 16:45

3 Answers3

4

It is not clear to me whether the IO priority can be set. The SetProcessInformation() call takes a PROCESS_INFORMATION_CLASS as an argument and that only defines ProcessMemoryPriority. I was having problems with a powershell script getting run out of task manager with a memory priority of 2 which was killing me. I am new to the PInvoke stuff and using it from PowerShell so I've probably violated at least one best practice, but the snippet below solved my problem.

The Add-Type stuff to load the functions via C#:

Add-Type @"
using System;
using System.Runtime.InteropServices;

namespace SysWin32
{
    public enum PROCESS_INFORMATION_CLASS
    {
        ProcessMemoryPriority,
        ProcessInformationClassMax,
    }

    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
    public struct MEMORY_PRIORITY_INFORMATION
    {
        public uint MemoryPriority;
    }

    public partial class NativeMethods {
        [System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint="GetCurrentProcess")]
        public static extern System.IntPtr GetCurrentProcess();

        [System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint="SetProcessInformation")]
        public static extern bool SetProcessInformation(System.IntPtr hProcess, PROCESS_INFORMATION_CLASS ProcessInformationClass, System.IntPtr ProcessInformation, uint ProcessInformationSize) ;
    }
}
"@

And here is the example using the functions:

$myProcessHandle = [SysWin32.NativeMethods]::GetCurrentProcess()
$memInfo = New-Object SysWin32.MEMORY_PRIORITY_INFORMATION
$memInfo.MemoryPriority = 5
$memInfoSize = [System.Runtime.Interopservices.Marshal]::SizeOf($memInfo)
$memInfoPtr = [System.Runtime.Interopservices.Marshal]::AllocHGlobal($memInfoSize)
[System.Runtime.Interopservices.Marshal]::StructureToPtr($memInfo, $memInfoPtr, $false)
$result = [SysWin32.NativeMethods]::SetProcessInformation($myProcessHandle, [SysWin32.PROCESS_INFORMATION_CLASS]::ProcessMemoryPriority, $memInfoPtr, $memInfoSize)
$result

Using procexp I was able to verify that my powershell script is now running with a memory priority of 5.

Peter Friend
  • 750
  • 1
  • 7
  • 17
1

Here's a PowerShell one-liner for reducing a process priority:

(get-process msosync).PriorityClass='BelowNormal'

In this PowerShell context, the valid values of PriorityClass can be one of: Normal, Idle, High, RealTime, BelowNormal, AboveNormal

You can test the results with this one-liner:

get-process msosync | Select-Object Name,PriorityClass,CPU | Format-Table -AutoSize

bcdady
  • 59
  • 3
0

Following on from Peter Friend's answer above, I wrote a powershell script that updates all 3 of the priorities in question (CPU, Memory and IO). I'll post it here because this is the #1 result in google for this question.

You can run it from Powershell like this -

.\SetProcessPriority.ps1 -ProcessName sqlservr -CpuPriorityClass Idle -MemoryPriority 1 -IoPriority 0
  • Options for CpuPriorityClass are - Idle, BelowNormal, Normal, AboveNormal, High, Realtime
  • Options for MemoryPriority are 1-5 (Setting this to 1 mimics what happens when you choose Process Explorer's "Background" "Low I/O and Memory Priority" option)
  • Options for IoPriority are 0 (Very Low), 1 (Low), 2 (Normal) (Setting this to 0 mimics what happens when you choose Process Explorer's "Background" "Low I/O and Memory Priority" option)

SetProcessPriority.ps1 code -

[CmdletBinding()]
Param (
    [string]$ProcessName = "sqlservr",
    [string]$CpuPriorityClass = "Idle",
    [int]$MemoryPriority = 1,
    [int]$IoPriority = 0
)

# If you can't run, execute this first from an elevated PowerShell Prompt - set-executionpolicy remotesigned
If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{   
    $arguments = "& '" + $myinvocation.mycommand.definition + "'"
    Start-Process powershell -Verb runAs -ArgumentList $arguments
    Break
}

Add-Type @"
using System;
using System.Runtime.InteropServices;

namespace SysWin32
{
    public enum PROCESS_INFORMATION_CLASS
    {
        ProcessMemoryPriority,
        ProcessInformationClassMax,
    }

    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
    public struct PROCESS_INFORMATION
    {
        public uint Information;
    }

    public partial class NativeMethods {
        [System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint="GetCurrentProcess", SetLastError=true)]
        public static extern System.IntPtr GetCurrentProcess();

        [System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint="OpenProcess", SetLastError=true)]
        public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);

        [System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint="SetProcessInformation", SetLastError=true)]
        public static extern bool SetProcessInformation(System.IntPtr hProcess, PROCESS_INFORMATION_CLASS ProcessInformationClass, System.IntPtr ProcessInformation, uint ProcessInformationSize) ;
    }
}

namespace SysWinNT
{
    public enum PROCESS_INFORMATION_CLASS
    {
        ProcessBasicInformation,
        ProcessQuotaLimits,
        ProcessIoCounters,
        ProcessVmCounters,
        ProcessTimes,
        ProcessBasePriority,
        ProcessRaisePriority,
        ProcessDebugPort,
        ProcessExceptionPort,
        ProcessAccessToken,
        ProcessLdtInformation,
        ProcessLdtSize,
        ProcessDefaultHardErrorMode,
        ProcessIoPortHandlers,          // Note: this is kernel mode only
        ProcessPooledUsageAndLimits,
        ProcessWorkingSetWatch,
        ProcessUserModeIOPL,
        ProcessEnableAlignmentFaultFixup,
        ProcessPriorityClass,
        ProcessWx86Information,
        ProcessHandleCount,
        ProcessAffinityMask,
        ProcessPriorityBoost,
        ProcessDeviceMap,
        ProcessSessionInformation,
        ProcessForegroundInformation,
        ProcessWow64Information,
        ProcessImageFileName,
        ProcessLUIDDeviceMapsEnabled,
        ProcessBreakOnTermination,
        ProcessDebugObjectHandle,
        ProcessDebugFlags,
        ProcessHandleTracing,
        ProcessIoPriority,
        ProcessExecuteFlags,
        ProcessTlsInformation,
        ProcessCookie,
        ProcessImageInformation,
        ProcessCycleTime,
        ProcessPagePriority,
        ProcessInstrumentationCallback,
        ProcessThreadStackAllocation,
        ProcessWorkingSetWatchEx,
        ProcessImageFileNameWin32,
        ProcessImageFileMapping,
        ProcessAffinityUpdateMode,
        ProcessMemoryAllocationMode,
        ProcessGroupInformation,
        ProcessTokenVirtualizationEnabled,
        ProcessConsoleHostProcess,
        ProcessWindowInformation,
        MaxProcessInfoClass             // MaxProcessInfoClass should always be the last enum
    }

    public partial class NativeMethods {
        [System.Runtime.InteropServices.DllImportAttribute("ntdll.dll", EntryPoint="NtSetInformationProcess")]
        public static extern int NtSetInformationProcess(System.IntPtr hProcess, PROCESS_INFORMATION_CLASS processInformationClass, System.IntPtr ProcessInformation, uint ProcessInformationSize);
    }
}
"@

$OverallResult = 0

$Process = Get-Process $ProcessName
$ProcessId = $Process.id
Try
{
    $Process.PriorityClass=$CpuPriorityClass
}
Catch
{
    Write-host -BackgroundColor Black -ForegroundColor Red "Error setting process priority  - $($_.Exception.Message)"
    pause
    $OverallResult = 1
    exit $OverallResult
}
Write-Host -ForegroundColor Green ("Set CPU piority on {0} ({1}) to be {2}" -f $ProcessName, $ProcessId, $CpuPriorityClass)

#    4096 or     0x1000 = PROCESS_QUERY_LIMITED_INFORMATION
# 1056763 or 0x00101ffb = PROCESS_ALL_ACCESS
$DesiredAccess = 0x00101ffb
$InheritHandle = $false
$hProcess = [SysWin32.NativeMethods]::OpenProcess($DesiredAccess, $InheritHandle, $ProcessId);
$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
if ($hProcess -eq 0) 
{
    Write-Host -BackgroundColor Black -ForegroundColor Red "Failed to open Win32 process.  Error: $(([ComponentModel.Win32Exception] $LastError).Message)"
    pause
    $OverallResult = 2
    exit $OverallResult
}
Write-Host -ForegroundColor Green ("Successfully got handle - {0}" -f $hProcess)

$memInfo = New-Object SysWin32.PROCESS_INFORMATION
$memInfo.Information = $MemoryPriority
$memInfoSize = [System.Runtime.Interopservices.Marshal]::SizeOf($memInfo)
$memInfoPtr = [System.Runtime.Interopservices.Marshal]::AllocHGlobal($memInfoSize)
[System.Runtime.Interopservices.Marshal]::StructureToPtr($memInfo, $memInfoPtr, $false)
$result = [SysWin32.NativeMethods]::SetProcessInformation($hProcess, [SysWin32.PROCESS_INFORMATION_CLASS]::ProcessMemoryPriority, $memInfoPtr, $memInfoSize)
$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
if (!$result)
{
    $OverallResult = 3
    Write-Host -BackgroundColor Black -ForegroundColor Red ("Failed to set memory piority on {0} ({1}) to be {2}.  Error: {3}" -f $ProcessName, $ProcessId, $MemoryPriority, ([ComponentModel.Win32Exception]$LastError).Message)
}
else
{
    Write-Host -ForegroundColor Green ("Set memory piority on {0} ({1}) to be {2}." -f $ProcessName, $ProcessId, $MemoryPriority)
}

$ioInfo = New-Object SysWin32.PROCESS_INFORMATION
$ioInfo.Information = $IoPriority
$ioInfoSize = [System.Runtime.Interopservices.Marshal]::SizeOf($ioInfo)
$ioInfoPtr = [System.Runtime.Interopservices.Marshal]::AllocHGlobal($ioInfoSize)
[System.Runtime.Interopservices.Marshal]::StructureToPtr($ioInfo, $ioInfoPtr, $false)
$result = [SysWinNT.NativeMethods]::NtSetInformationProcess($hProcess, [SysWinNT.PROCESS_INFORMATION_CLASS]::ProcessIoPriority, $ioInfoPtr, $ioInfoSize)
$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
if ($result -ne 0)
{
    $OverallResult = 4
    Write-Host -BackgroundColor Black -ForegroundColor Red ("Failed to set IO piority on {0} ({1}) to be {2}.  Result: {3}.  Error: {4}" -f $ProcessName, $ProcessId, $IoPriority, $result, ([ComponentModel.Win32Exception]$LastError).Message)
}
else
{
    Write-Host -ForegroundColor Green ("Set IO piority on {0} ({1}) to be {2}" -f $ProcessName, $ProcessId, $IoPriority)
}
exit $OverallResult
mattphi
  • 1
  • 1