%20Win10%20%D1%87%D0%B5%D1%80%D0%B5%D0%B7%20OpenSSH.png)
Существует множество решений для локального отключения дисплея на компьютере с Windows 10. Все они представляют собой некоторую форму следующей строки SendMessage. Также есть небольшие исполняемые файлы, такие как nircmd, которые делают это. Однако, похоже, есть некоторые ограничения при запуске любого из них через OpenSSH. Поскольку мой OpenSSH настроен на использование тех же учетных данных, что и мой локальный пользователь, я не могу понять, почему ничего не происходит. Версии скрипта ps возвращают простую 1, а решения, такие как nircmd, просто ничего не возвращают. Даже ошибки. Есть ли у вас какие-либо соображения, что может здесь произойти и как заставить это работать?
Пример сценария:
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,2)
правка: возможно, мне следует добавить, что другоеnircmdтакие опции, как отключение звука, работают без проблем.
решение1
Это происходит потому, что интерактивный сеанс Windows не является текущим сеансом, поэтому он не работает в контексте, где физический дисплей активно подключен. Звук и другие функции подключены, но дисплей привязан к сеансу. Вы можете либо войти в систему интерактивно, либо использовать что-то вроде psexec для выполнения процесса powershell в контексте пользователя. Если вы не против использования psexec, то можете использовать это:
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 int SendMessage(int hWnd, int hMsg, int wParam, int lParam);' -Name a -Pas)::SendMessage(-1,0x0112,0xF170,2)
Однако для этого вам понадобится psexec.
Если интерактивных сеансов несколько, он будет выполнен более одного раза.
При запуске из пакета вам необходимо заменить оба %s на %%s.
Это часть, которая собирает интерактивную сессию:
FOR /F "usebackq tokens=4" %s IN (`tasklist /nh /fo table /fi "imagename eq explorer.exe"`) DO echo %s
Следующий код можно скопировать в пакетный файл и запустить из эмулятора терминала.
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 -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,2)"
)
Единственное отличие в том, что каждый из них %s
был изменен на %%s
.
Имейте в виду, что запуск его в интерактивном режиме на компьютере, на котором вы пытаетесь отключить дисплеи, ВЕРОЯТНО НЕ УДАСТСЯ. Это происходит потому, что ваш интерактивный сеанс все еще активен.
Чтобы вывести экраны из спящего режима, вы можете использовать следующее (проверено и работает на нескольких моих устройствах):
:: 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