How to set Low I/O (“background”) priority in Powe

2019-05-17 21:47发布

问题:

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?

回答1:

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.



回答2:

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