如何在 Powershell 中设置低 I/O(“后台")优先级

问题描述:

这个 powershell 脚本可以将进程的优先级从空闲"设置为实时",但有些工具提供了另一个优先级甚至低于进程的优先级:

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:

如何在 Powershell 中设置?

How to set that in Powershell?

IO 优先级是否可以设置我不清楚.SetProcessInformation() 调用将 PROCESS_INFORMATION_CLASS 作为参数,并且仅定义 ProcessMemoryPriority.我在用内存优先级为 2 的任务管理器耗尽 powershell 脚本时遇到了问题,这让我很沮丧.我是 PInvoke 的新手,并在 PowerShell 中使用它,所以我可能至少违反了一项最佳实践,但下面的代码段解决了我的问题.

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.

通过 C# 加载函数的 Add-Type 内容:

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) ;
    }
}
"@

这是使用函数的示例:

$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

使用 procexp 我能够验证我的 powershell 脚本现在正在以 5 的内存优先级运行.

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