经过几个月的放弃,我想重新考虑这个看似非常简单的想法。我想要一个脚本,在我的显示器进入睡眠状态后将其唤醒。我尝试了几乎所有我能想到的方法,请有人救救我,让我不要再养一只狗,它会抓着骨头形状的蓝牙鼠标,并在过程中摇晃它(是的,我就是这么绝望)
我目前所做的:
1)在远程 Win10 机器上安装 OpenSSH(有效)
2)获取交互式 Windows 会话对实际会话拥有权限:
FOR /F "usebackq tokens=4" %s IN (`tasklist /nh /fo table /fi "imagename eq explorer.exe"`) DO ...
3a) 启动其中一个许多保持 Windows 唤醒程序。这些程序不起作用,因为它们从未由 psexec 或 powershell 启动。或者至少如果它们运行,它们无法显示并且不执行任何操作。这是我尝试启动的任何进程的情况。
3b)SendMessage
像我一样使用让它进入睡眠状态:
psexec -accepteula -nobanner -d -i %%s -w "%windir%" powershell (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)
传递 2 作为最后一个参数可以完美关闭显示器。传递其他任何值(例如 -1 表示开启)均不起作用。
3c)现在我绝望了,我试图做一个鼠标摆动/按键模拟ETC。:
FOR /F "usebackq tokens=4" %%s IN (`tasklist /nh /fo table /fi "imagename eq explorer.exe"`) DO psexec -accepteula -nobanner -d -i %%s -w "%windir%" powershell (Add-Type '[DllImport(\"user32.dll\")]^public static extern void mouse_event(uint dwFlags, int dx, int dy, uint dwData, int dwExtraInfo);' -Name user32 -PassThru)::mouse_event(1,40,0,0,0)
使用提升的权限在本地执行。与 SSH 一起使用时会短暂弹出 powershell。不会进行任何鼠标摆动。
3d) 使用老旧的 nircmd.exe 监视器关闭或类似专用的打开监视器实用程序。结果与 3a) 相同
许多链接的帖子都有所谓的解决方案,但没有一个对我有用。我能看出在本地执行脚本和通过 ssh 执行脚本的唯一区别是输出类似
powershell started on <mywin10pc> with process ID xxxxx
除此之外,我无法知道发生了什么。我在脚本末尾放置了一个 echo 0 来检查它是否已执行。它总是给我 0。有人知道我错过了什么吗?特别是 3b) 对我来说很奇怪,因为它可以使显示器进入睡眠状态。
答案1
问题是唤醒显示器和将计算机设置为活动状态是两回事。发送 -1 来唤醒显示器做唤醒显示器。不幸的是,这也不足以唤醒计算机。为此,您可以使用SetThreadExecutionState
。这是一个有效的批处理示例:
@ECHO OFF
:: gather session handle
FOR /F "usebackq tokens=4" %%s IN (`tasklist /nh /fo table /fi "imagename eq explorer.exe"`) DO SET hsession=%%s
:: wake display
psexec -accepteula -nobanner -d -i %hsession% -w "%windir%" powershell -NoProfile -NoLogo -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)"
CALL :wait 2
:: reactivate session
psexec -accepteula -nobanner -d -i %hsession% -w "%windir%" powershell -NoProfile -NoLogo -Command "$x=Add-Type '[DllImport(\"kernel32.dll\")]public static extern void SetThreadExecutionState(uint esFlags);' -name System -namespace Win32 -passThru;$x::SetThreadExecutionState([uint32]\"0x03\");Sleep 5;$x::SetThreadExecutionState([uint32]\"0x40\");"
CALL :wait 2
GOTO:EOF
:wait
SET dowait=%~1
IF "%dowait%"=="" SET dowait=10
ping -n %dowait% 127.0.0.1 >NUL
GOTO:EOF
在某些环境中,仅使用命令是可能的SetThreadExecutionState
,但在我的测试中,它并不是 100% 可靠。这也不会唤醒不支持它的设备。
答案2
你可能真的想太多了。你只是想让显示器保持唤醒状态吗?还是你特别想让它们在关闭后才打开?我使用了一个叫做摆动鼠标过去。它只是在您指定的持续时间后将鼠标左右移动 1 个像素。当您实际使用鼠标时,您不会注意到移动,但它会保持屏幕处于活动状态(并且具有在大多数即时通讯应用程序(如 Lync 或 Slack)中显示您处于活动状态的额外好处)