【问题标题】:How to stop a windows 10 machine from sleeping/hibernating down when running a powershell process?运行PowerShell进程时如何阻止Windows 10机器休眠/休眠?
【发布时间】:2021-03-17 06:52:05
【问题描述】:

我有一个 powershell 进程,它从远程服务器读取记录并将它们复制到本地数据库中。运行时,可能会运行 8-12 小时。

如何防止计算机在此期间关闭(或进入睡眠/休眠模式)?我知道我可以调整“电源和睡眠设置”以将计算机设置为永不睡眠,但这不是我想要的 - 我确实希望它在进程进入睡眠状态>没有运行。

我知道如果 netflix 或 youtube 视频正在运行,睡眠/休眠会暂停,我希望计算机在 powershell 进程运行时也这样做。

powershell 进程在桌面上的命令窗口中运行 - 我很高兴屏幕保护程序激活,但我不希望发生的是让我在 8 小时后唤醒机器并发现该进程只跑了 10 分钟,电脑就进入睡眠状态!

【问题讨论】:

  • 查看此链接:stackoverflow.com/questions/2284601/…,然后找到将其从 c# 转换为 PowerShell 的方法。使用反射可以做到。
  • 如果您已经有一个工作脚本,那么您可以在任务计划程序中创建一个新任务,有一个条件选项卡,您可以在其中勾选“唤醒计算机以运行此任务”复选框
  • @Iww - 我已经这样做了! - 任务调度程序唤醒以启动进程,但不久之后计算机再次进入睡眠状态!

标签: powershell windows-10 sleep


【解决方案1】:

通过一些额外的努力,您可以使用标准powercfg.exe utility实现所需的行为,方法是使用按需创建的自定义、始终开启的电源方案并在脚本运行期间临时激活:

注意:

  • 在下方寻找评论# YOUR CODE GOES HERE

  • 有关 .NET/基于 Windows API 的替代方案,请参阅this answer

# Define the properties of a custom power scheme, to be created on demand.
$schemeGuid = 'e03c2dc5-fac9-4f5d-9948-0a2fb9009d67' # randomly created with New-Guid
$schemeName = 'Always on'
$schemeDescr = 'Custom power scheme to keep the system awake indefinitely.'

# Helper function that ensures that the most recent powercfg.exe call succeeded.
function assert-ok { if ($LASTEXITCODE -ne 0) { throw } }

# Determine the currently active power scheme, so it can be restored at the end.
$prevGuid = (powercfg -getactivescheme) -replace '^.+([-0-9a-f]{36}).+$', '$1'
assert-ok

# Temporarily activate a custom always-on power scheme; create it on demand.
try {

  # Try to change to the custom scheme.
  powercfg -setactive $schemeGuid 2>$null
  if ($LASTEXITCODE -ne 0) { # Changing failed -> create the scheme on demand.
    # Clone the 'High performance' scheme.
    $null = powercfg -duplicatescheme SCHEME_MIN $schemeGuid
    assert-ok
    # Change its name and description.
    $null = powercfg -changename $schemeGuid $schemeName $schemeDescr
    # Activate it
    $null = powercfg -setactive $schemeGuid
    assert-ok
    # Change all settings to be always on.
    # Note: 
    #   * Remove 'monitor-timeout-ac', 'monitor-timeout-dc' if it's OK
    #     for the *display* to go to sleep.
    #   * If you make changes here, you'll have to run powercfg -delete $schemeGuid 
    #     or delete the 'Always on' scheme via the GUI for changes to take effect.
    #   * On an AC-only machine (desktop, server) the *-ac settings aren't needed.
    $settings = 'monitor-timeout-ac', 'monitor-timeout-dc', 'disk-timeout-ac', 'disk-timeout-dc', 'standby-timeout-ac', 'standby-timeout-dc', 'hibernate-timeout-ac', 'hibernate-timeout-dc'
    foreach ($setting in $settings) {
      powercfg -change $setting 0 # 0 == Never
      assert-ok
    }
  }
  
  # YOUR CODE GOES HERE.
  # In this sample, wait for the user to press Enter before exiting.
  # Before that, the 'Always on' power scheme should remain in
  # effect, and the machine shouldn't go to sleep.
  pause

} finally { # Executes even when the script is aborted with Ctrl-C.
  # Reactivate the previously active power scheme.
  powercfg -setactive $prevGuid
}

您可以从上面创建一个 wrapper 脚本,将要执行的脚本的路径传递给该脚本。

【讨论】:

    【解决方案2】:

    要为powercfg.exe-based solution 提供基于.NET / Windows API 的替代方案

    注意:

    • 该解决方案使用Add-Type 按需编译 C# 代码,这会在当前会话中首次调用代码时导致性能损失。

    • 请务必在同一会话中调用::StayAwake($false),以清除发出的电源请求。

    • 在下方寻找评论# YOUR CODE GOES HERE

    • 此解决方案由MarkusEgle 改编自this C# answer

    Add-Type -ErrorAction Stop -Name PowerUtil -Namespace Windows -MemberDefinition @'
    
        // Member variables.
        static IntPtr _powerRequest;
        static bool _mustResetDisplayRequestToo;
    
        // P/Invoke function declarations.
        [DllImport("kernel32.dll")]
        static extern IntPtr PowerCreateRequest(ref POWER_REQUEST_CONTEXT Context);
    
        [DllImport("kernel32.dll")]
        static extern bool PowerSetRequest(IntPtr PowerRequestHandle, PowerRequestType RequestType);
    
        [DllImport("kernel32.dll")]
        static extern bool PowerClearRequest(IntPtr PowerRequestHandle, PowerRequestType RequestType);
    
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        static extern int CloseHandle(IntPtr hObject);
    
        // Availablity Request Enumerations and Constants
        enum PowerRequestType
        {
            PowerRequestDisplayRequired = 0,
            PowerRequestSystemRequired,
            PowerRequestAwayModeRequired,
            PowerRequestMaximum
        }
    
        const int POWER_REQUEST_CONTEXT_VERSION = 0;
        const int POWER_REQUEST_CONTEXT_SIMPLE_STRING = 0x1;
    
        // Availablity Request Structures
        // Note:  Windows defines the POWER_REQUEST_CONTEXT structure with an
        // internal union of SimpleReasonString and Detailed information.
        // To avoid runtime interop issues, this version of 
        // POWER_REQUEST_CONTEXT only supports SimpleReasonString.  
        // To use the detailed information,
        // define the PowerCreateRequest function with the first 
        // parameter of type POWER_REQUEST_CONTEXT_DETAILED.
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        struct POWER_REQUEST_CONTEXT
        {
            public UInt32 Version;
            public UInt32 Flags;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string SimpleReasonString;
        }
    
        /// <summary>
        /// Prevents the system from going to sleep, by default including the display.
        /// </summary>
        /// <param name="enable">
        ///   True to turn on, False to turn off. Passing True must be paired with a later call passing False.
        ///   If you pass True repeatedly, subsequent invocations take no actions and ignore the parameters.
        ///   If you pass False, the remaining paramters are ignored.
        //    If you pass False without having passed True earlier, no action is performed.
        //// </param>
        /// <param name="includeDisplay">True to also keep the display awake; defaults to True.</param>
        /// <param name="reasonString">
        ///   A string describing why the system is being kept awake; defaults to the current process' command line.
        ///   This will show in the output from `powercfg -requests` (requires elevation).
        /// </param>
        public static void StayAwake(bool enable, bool includeDisplay = true, string reasonString = null)
        {
          
          if (enable)
          {
    
            // Already enabled: quietly do nothing.
            if (_powerRequest != IntPtr.Zero) { return; }
    
            // Configure the reason string.
            POWER_REQUEST_CONTEXT powerRequestContext;
            powerRequestContext.Version = POWER_REQUEST_CONTEXT_VERSION;
            powerRequestContext.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
            powerRequestContext.SimpleReasonString = reasonString ?? System.Environment.CommandLine; // The reason for making the power request.
    
            // Create the request (returns a handle).
            _powerRequest = PowerCreateRequest(ref powerRequestContext);
    
            // Set the request(s).
            PowerSetRequest(_powerRequest, PowerRequestType.PowerRequestSystemRequired);
            if (includeDisplay) { PowerSetRequest(_powerRequest, PowerRequestType.PowerRequestDisplayRequired); }
            _mustResetDisplayRequestToo = includeDisplay;
    
          }
          else
          {
    
            // Not previously enabled: quietly do nothing.
            if (_powerRequest == IntPtr.Zero) { return; }
    
            // Clear the request
            PowerClearRequest(_powerRequest, PowerRequestType.PowerRequestSystemRequired);
            if (_mustResetDisplayRequestToo) { PowerClearRequest(_powerRequest, PowerRequestType.PowerRequestDisplayRequired); }
            CloseHandle(_powerRequest);
            _powerRequest = IntPtr.Zero;
    
          }
      }
    
      // Overload that allows passing a reason string while defaulting to keeping the display awake too.
      public static void StayAwake(bool enable, string reasonString)
      {
        StayAwake(enable, false, reasonString);
      }
    
    '@
    
    try {
    
      # Create power request(s) that keep the system awake.
      # Pass $false as the 2nd argument to allow the display to go to sleep.
      # The reason string is visible when you run `powercfg.exe -requests` to show current requests
      # (requires elevation).
      # Defaults: keep the display awake too, use the current process' command line as the reason string.
      [Windows.PowerUtil]::StayAwake($true, $true, "Running long-running script $PSCommandPath.")
    
      # YOUR CODE GOES HERE.
      # In this sample, wait for the user to press Enter before exiting.
      # Before that, the system should stay awake indefinitely.
      pause
    
    } finally { # This ensures that the previous scheme is restored even when the script is aborted with Ctrl-C.
    
      # Clear the power requests.
      [Windows.PowerUtil]::StayAwake($false)
    
    }
    

    【讨论】:

      【解决方案3】:

      我使用的简单单线:

      Powercfg /x -standby-timeout-ac 0
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-03-07
        • 2020-08-31
        • 2012-08-23
        • 1970-01-01
        • 2015-07-19
        • 2018-12-21
        • 2014-05-12
        相关资源
        最近更新 更多