Windows 唤醒屏幕:SendMessage SC_MONITORPOWER 与 SendInput 模拟鼠标

Windows 提供了两种方式唤醒熄屏的显示器:发送系统消息或模拟鼠标输入。

PowerShell 一行命令

powershell -command "(Add-Type '[DllImport(\"user32.dll\")]^public static extern int SendMessage(int hWnd,int hMsg,int wParam,int lParam);' -Name a -Pas)::SendMessage(-1,0x0112,0xF170,-1)"

0x0112WM_SYSCOMMAND0xF170SC_MONITORPOWER,最后参数 -1 表示打开显示器(2 关闭,1 低功耗)。

C++ SendMessage

#include <windows.h>

int main() {
    SendMessage(HWND_BROADCAST,
                WM_SYSCOMMAND,
                SC_MONITORPOWER,
                -1);
    return 0;
}

SC_MONITORPOWER 的第四个参数含义:

  • -1 = 打开显示器
  • 1 = 低功耗
  • 2 = 关闭显示器

更可靠:模拟鼠标移动(推荐)

部分机器上 SC_MONITORPOWER 不一定生效,模拟极小鼠标移动更稳定:

#include <windows.h>

int main() {
    INPUT input = {0};
    input.type = INPUT_MOUSE;
    input.mi.dx = 1;
    input.mi.dy = 1;
    input.mi.dwFlags = MOUSEEVENTF_MOVE;
    SendInput(1, &input, sizeof(INPUT));
    return 0;
}

等效于”假装用户动了一下鼠标”,几乎在所有机器上都能触发屏幕唤醒。

PowerShell 版本

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

public class WinAPI {
    [DllImport("user32.dll")]
    public static extern void mouse_event(
        int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
}
"@

[WinAPI]::mouse_event(1, 0, 1, 0, 0)

Session 0 限制

如果代码在 Windows 服务里运行,以上方法大概率无效,因为服务运行在 Session 0,无法操作用户桌面。常见解决方案:

  • 改用计划任务(交互式模式运行)
  • 注入用户 Session 进程
  • 使用 WTSSendMessage 跨 Session 通信

这是服务程序操控 GUI 时的常见踩坑点。