为什么我的 Windows 10 PC 在调用 SetWaitableTimer() 后没有唤醒?

Why Isn't My Windows 10 PC Waking Up after a SetWaitableTimer() Call?

我有两台 Windows 10 PC,都是 运行 Fall Creators Update,安装了所有最新补丁。一个在通过 CreateWaitableTimer/SetWaitableTimer 设置定时器后从睡眠中醒来,另一个没有......这是一个问题,因为非唤醒的是我的 DVR,需要能够按需唤醒: ).

都没有启用休眠。

我在拒绝唤醒的系统上看不到任何异常事件。它只是不唤醒,除非我手动唤醒或向它发送局域网唤醒数据包。

这是我在两个系统上 运行 的 C# 测试代码:

public class Program
{
[ DllImport( "kernel32.dll" ) ]
private static extern SafeWaitHandle CreateWaitableTimer( IntPtr lpTimerAttributes, bool bManualReset,
    string lpTimerName );

[ DllImport( "kernel32.dll", SetLastError = true ) ]
[ return : MarshalAs( UnmanagedType.Bool ) ]
private static extern bool SetWaitableTimer( SafeWaitHandle hTimer, [ In ] ref long pDueTime, int lPeriod,
    IntPtr pfnCompletionRoutine, IntPtr lpArgToCompletionRoutine, bool fResume );

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CancelWaitableTimer(IntPtr hTimer);

[DllImport("powrprof.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent);

private static ILogger _logger;

private static bool Hibernate()
{
    bool retVal = SetSuspendState(true, false, false);

    _logger.Information(retVal
        ? $"Returning from hibernation at {DateTime.Now.ToLongTimeString()}"
        : $"Failed to enter hibernation, error message was {Marshal.GetLastWin32Error()}");

    return retVal;
}

private static bool Sleep()
{
    bool retVal = SetSuspendState(false, false, false);

    _logger.Information( retVal
        ? $"Returning from sleep at {DateTime.Now.ToLongTimeString()}"
        : $"Failed to enter sleep, error message was {Marshal.GetLastWin32Error()}" );

    return retVal;
}

private static void SetWakeTimer( int minutes, bool hibernate )
{
    DateTime utc = DateTime.Now.AddMinutes( minutes );
    long duetime = utc.ToFileTime();

    using( SafeWaitHandle handle = CreateWaitableTimer( IntPtr.Zero, true, "SleepWakeTimerTest" ) )
    {
        if( SetWaitableTimer( handle, ref duetime, 0, IntPtr.Zero, IntPtr.Zero, true ) )
        {
            _logger.Information($"Timer set, will trigger at {utc.ToLongTimeString()}");

            if ( hibernate ) Hibernate();
            else Sleep();
        }
        else
            Console.WriteLine($"CreateWaitableTimer failed, error message was {Marshal.GetLastWin32Error()}");
    }
}

static void Main( string[] args )
{
    _logger = new LoggerConfiguration()
        .WriteTo.File( $"log-{DateTime.Now:yyyy-M-d-hhmmss}.txt" )
        .CreateLogger();

    _logger.Information("parsing command line arguments...");

    var cmdLine = new FluentCommandLineParser();

    int delay = 2;
    bool hibernate = false;

    cmdLine.Setup<int>( 'd', "delay" )
        .Callback( x => delay = x )
        .SetDefault( 2 )
        .WithDescription( "wakeup delay, in minutes" );

    cmdLine.Setup<bool>( 'h', "hibernate" )
        .Callback( x => hibernate = x )
        .SetDefault( false )
        .WithDescription( "hibernate if flag set, otherwise sleep" );

    SetWakeTimer( delay, hibernate );
}
}

非常感谢有关检查内容或采取哪些额外诊断步骤的建议。

附加信息

有人建议我尝试通过手动定义的计划任务(即使用 Task Scheduler 应用程序)唤醒计算机。有趣的是,任务并没有唤醒电脑。

在 Fall Creators Update 的升级过程中,一项关键的电源管理设置发生了变化。

在高级电源设置 -> 睡眠 -> 允许唤醒定时器下,之前的启用设置已更改为仅重要唤醒定时器。 "Important Wake Timers Only" 是最近引入的新设置。

此更改导致无法唤醒的系统忽略软件中安排的唤醒事件。基本上,它旨在仅允许操作系统唤醒。

将设置恢复为启用解决了问题。