
Existem muitas soluções para desligar a exibição localmente em uma máquina Windows10. Todos eles são alguma forma da seguinte linha SendMessage. Existem também pequenos executáveis como o nircmd que fazem isso. No entanto, parece haver alguma limitação ao executar qualquer um deles via OpenSSH. Como meu OpenSSH está configurado para usar exatamente as mesmas credenciais do meu usuário local, não consigo entender por que nada acontece. As versões do script ps retornam um simples 1, e soluções como nircmd simplesmente não retornam nada. Nem mesmo um erro. Alguma ideia do que pode acontecer aqui e como fazer funcionar?
Roteiro de exemplo:
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)
editar: talvez eu deva adicionar aquele outronircmdopções como silenciar o áudio funcionam sem problemas.
Responder1
Isso ocorre porque a sessão interativa do Windows não é a sessão atual e, portanto, não está em execução em um contexto em que a exibição física esteja ativamente conectada. O som e outros recursos sim, mas a exibição está vinculada a uma sessão. Você pode fazer login interativamente ou usar algo como psexec para executar o processo do PowerShell no contexto do usuário. Se você concorda em usar o psexec, você pode usar isto:
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)
Você precisará do psexec para isso.
Se houver mais de uma sessão interativa, ela será executada mais de uma vez.
Se estiver executando em lote, você precisará substituir %s por %%s.
Esta é a parte que coleta a sessão interativa:
FOR /F "usebackq tokens=4" %s IN (`tasklist /nh /fo table /fi "imagename eq explorer.exe"`) DO echo %s
O seguinte pode ser copiado em um arquivo em lote e executado a partir de um emulador de terminal.
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)"
)
A única diferença é que cada um %s
foi alterado para %%s
.
Esteja ciente de que executá-lo interativamente no computador em que você está tentando desativar as exibições PROVAVELMENTE FALHARÁ. Isso ocorre porque sua sessão interativa ainda está ativa.
Para ativar suas telas, você pode usar o seguinte (testado e funciona em vários dos meus dispositivos):
:: 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