如何使用脚本使远程计算机远离睡眠模式?

How can I use a script to keep a remote computer from sleep mode?

我们正在尝试创建一个脚本,告诉计算机列表保持清醒。

我四处货比三家,决定使用我相信在这里找到的一个,但我无法让它在远程系统上工作。我之前尝试过 invoke-command,然后 -filepath 到脚本,并指定了计算机名称,但它没有任何作用。我做错了什么?

function workflow-Scrollock {
  Clear-Host
  Echo "Keep-alive with Scroll Lock..."
  $WShell = New-Object -com "Wscript.Shell"
  while ($true)
  {
    $WShell.sendkeys("{CAPSLOCK}")
    Start-Sleep -Milliseconds 2000
    $WShell.sendkeys("{CAPSLOCK}")
    Start-Sleep -Seconds 2
  }
}

我想看到远程计算机打开和关闭它的大写锁定,直到我重新启动它或停止脚本。

只要您的主要目标是保持计算机处于唤醒状态(而不是闪烁 Caps Lock 键),此 answer to a related question 应该会有所帮助。基本上你只需要通过一些修改将所有 C# 转换为 Add-Type,例如:

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

    public class PowerManager {
        POWER_REQUEST_CONTEXT _PowerRequestContext;
        IntPtr _PowerRequest; // HANDLE

        // Availability Request Functions
        [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)]
        internal 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;
        const int POWER_REQUEST_CONTEXT_DETAILED_STRING = 0x2;

        // Availablity Request Structure
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct POWER_REQUEST_CONTEXT
        {
            public UInt32 Version;
            public UInt32 Flags;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string SimpleReasonString;
        }

        public void EnableConstantDisplayAndPower(bool enable, string reason)
        {
            if (enable)
            {
                // Set up the diagnostic string
                _PowerRequestContext.Version = POWER_REQUEST_CONTEXT_VERSION;
                _PowerRequestContext.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
                _PowerRequestContext.SimpleReasonString = reason; // your reason for changing the power settings

                // Create the request, get a handle
                _PowerRequest = PowerCreateRequest(ref _PowerRequestContext);

                // Set the request
                PowerSetRequest(_PowerRequest, PowerRequestType.PowerRequestSystemRequired);
                PowerSetRequest(_PowerRequest, PowerRequestType.PowerRequestDisplayRequired);
            }
            else
            {
                // Clear the request
                PowerClearRequest(_PowerRequest, PowerRequestType.PowerRequestSystemRequired);
                PowerClearRequest(_PowerRequest, PowerRequestType.PowerRequestDisplayRequired);

                CloseHandle(_PowerRequest);
            }
        }
    }
"@
(New-Object PowerManager).EnableConstantDisplayAndPower($true, "Keeping the computer awake")
Wait-Event

我稍微清理了一下,删除了一些不用的东西,把它变成了 class,然后添加了 Wait-Event,这样它就会保持 运行。

现在您只需远程执行即可:

Invoke-Command -AsJob -ComputerName remotecomputer -FilePath C:\Path\To\Set-KeepAwake.ps1

您可以通过检查 powercfg /requests:

来证明它正在工作
Invoke-Command -ComputerName remotecomputer -ScriptBlock { powercfg /requests }

输出:

DISPLAY:
None.

SYSTEM:
[PROCESS] \Device\HarddiskVolume1\Windows\System32\wsmprovhost.exe
Keeping the computer awake

AWAYMODE:
None.