This is because the interactive Windows session is not the current session, so it's not running in a context where the physical display is actively connected. Sound and other features are, but the display is tied to a session. You can either login interactively, or use something like psexec to execute the powershell process in the context of the user. If you're okay with using psexec then you can use this:
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)
You will need psexec for this, though.
If there are more than one interactive sessions, it will be executed more than once.
If running from batch you'll need to replace both %s with %%s.
This is the part that collects the interactive session:
FOR /F "usebackq tokens=4" %s IN (`tasklist /nh /fo table /fi "imagename eq explorer.exe"`) DO echo %s
The following can be copied into a batch file and run from a terminal emulator.
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)"
)
The only difference is that each %s
was changes to %%s
.
Be aware that running it interactively on the computer that you're trying to disable the displays on WILL LIKELY FAIL. This is because your interactive session is still active.
To wake your screens you can use the following (tested and works on several of my devices):
:: 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
Some more utilities to try: Turn Off Monitor or Display Power Off Utility or ScreenOff.
– harrymc – 2018-12-10T14:03:41.950Thx, but those all have the same effect. They work locally on the machine, but not executed via ssh. That leads me to believe that somehow the ssh can't see/enumerate/detect displays to shut off. But without any log or error message i'm out of ideas. – narfelchen – 2018-12-10T17:33:32.110
Are you doing Windows-to-Windows? – harrymc – 2018-12-10T19:36:08.967
Since you are using OpenSSH, this means you are going form Linux to Windows, as it really would not be a go to for Windows to Windows, just use normal Windows PSRemoting. Now, all that being said, why are you trying to turn off a Windows display from a Linux box remotely. Just curious, or are you on a local Windows using an SSH session, again, not sure why you'd want to do that. – postanote – 2018-12-10T20:30:49.563
It's a simple convenience thing. I want to be able to switch the displays on my desktop on and off from a home automation system running on a raspberry pi. Of course there are solutions like automatic switch off in idle time for the displays but that's not on demand and i just like to switch between them at my convenience. Not the end of the world, just became a curiosity thing since everything else works (e.g. switching audio devices). – narfelchen – 2018-12-11T06:02:12.570
A session can contain multiple Window stations and a Window station can contain multiple Desktops. I assume that your SSH session creates a new session but does not create a Desktop thus there is no receiver to pick up your message. I can't find a definitive answer to this so this might well be wrong but it might give you something to look at. – Lieven Keersmaekers – 2018-12-11T06:20:54.837
If it wasn't for all the audio stuff working i would think that's it. But somehow the audio system appears to be abstracted to the ssh session. Also i was under the impression that the session was basically the same thing because its running in the local user context that is logged in. But then again, i can't find any info where to look what the ssh user can and cannot do. Every search returns me to people looking for answers on linux. Which makes of course makes sense, but still. Every document on the web seems to explain installation and then stop. – narfelchen – 2018-12-11T16:53:05.373