Windows – Catching screens turning on/off and running script or program when it happens

eventssleeptask schedulerwindows 7

I'm attempting to automatize lights around the man cave, ideally i would like to have the lights to be on as long as the computer screens are on and the lights go off when screensaver kicks in, without using any additional resident software.

So far i managed to catch events 4802 (screensaver start) and 4803 (screensaver stop) and using task scheduler and curl script to fire http request to the machine that handles the lights, and it works, to an extent.

Problem is that whenever the machine enters low power state, screensaver gets killed and 4803 is logged, and i can't differentiate between screensaver being killed by user input or by the windows entering low power state.

Basically i need to catch some events that happen when the screens turn off and on. Is there anything (in generic win7 installation) i could hitch the task on to?

Thanks.

EDIT:

I apologize to people who already answered this question, my question was not worded clearly enough. The machine in question does not actually enter sleep state, hence there is no event 42(kernel-power) or event 1(power-troubleshooter) generated in event logs, the machine only enters some kind of low-power state where it consumes about 53W, instead of the usual 180W, while i could use this to track the power state of this one specific machine, i would not be able to use the same method of detection for the other 3 computers in the room, since they do not have the required hardware (UPS) connected to them.

What i am looking for, is events that occur whenever monitors of the computer are powered off and back on by windows (not by their respective power buttons) as a result of the windows power management. Basically anything that would allow me to synchronize the lights in the cave with the state of the monitors and allow the task scheduler to fire off script that manipulates the lights.

Best Answer

  • Hopefully you've found another solution for this task by now, either way this was an interesting problem I wanted to take a crack at, and maybe someone else will benefit. Rather than trying to monitor screensaver states, my solution uses the "idleness" monitoring options within task scheduler. While this was built on Windows 10, I believe the functions used should be the same in W7.

    Overview

    • The "Idle" windows scheduled task triggers the "Idle" script, and uses the built in idle options on the conditions tab to wait till computer is idle to start, and then stop if/when the computer ceases to be idle.
    • The "Idle" script triggers the "Watcher" script, takes your chosen action (dim lights) then continues to run waiting on explorer.exe to exit, which will (should) never happen.
    • The "Watcher" script finds the process for the "Idle" script and waits on it to exit before completing its action (turn lights back on).

    Basic path of events

    1. The "Idle" task attempts to run every 1 minute, but only will run if PC has been idle for your chosen amount of time.
    2. "Idle" task runs the "Idle" script. The script triggers "Watcher" script, triggers your chosen action (dim lights), and then uses the "wait-process" cmdlet to wait for explorer.exe to exit, which should never happen assuming Windows is stable, and therefor continues to run as long as PC is idle.
    3. "Watcher" script starts and watches for the process of the "Idle" script to exit.
    4. User input causes PC to exit idle state, killing the "Idle" task, therefore killing the powershell.exe process of the "Idle" script.
    5. "Watcher" script sees the "Idle" script process exit, turns the lights back on and then exits.

    Setup

    1. Create your script folder which will contain both scripts.
    2. Copy the powershell executable into your new folder folder:

      "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" >>>> C:\scripts\dimlights\
      
    3. Create "Idle.ps1" and paste in script. On the first line of the script, specify your folder containing scripts and copy of powershell.exe:

      $myScriptDir = "C:\scripts\dimlights\"
      #============= Variables ==================
      $logfile = join-path $myScriptDir log.txt
      $nid = (Get-Process explorer).Id
      $mydate = Get-date
      
      #============= Code ==================
      start-process powershell.exe -argumentlist "-NonInteractive –ExecutionPolicy Bypass -file $myScriptDir\watcher.ps1"
      echo "$mydate - PID: $nid - Idle start action" | out-file -Append $logfile
      #----------------Insert chosen action code here----------------
      Wait-Process $nid
      

      $mydate = Get-date echo "$mydate - PID: $nid - Last line in Idle, should not have been reached." | out-file -Append $logfile

    4. Create "Watcher.ps1" in same folder and paste in script, again specifying the folder:

      $myScriptDir = "C:\scripts\dimlights\"
      #============= Variables ==================
      $myPSPath = join-path $myScriptDir powershell.exe
      $logfile = join-path $myScriptDir log.txt
      $nid = (Get-Process powershell | Where-Object {$_.path -eq $myPSPath}).id
      $mydate = Get-date
      
      #============= Code ==================
      echo "$mydate - PID: $nid - Watcher started" | out-file -Append $logfile
      if ($nid -ne $null){
      Wait-Process -id $nid
      $mydate = Get-date
      echo "$mydate - PID: $nid - Watcher end action" | out-file -Append $logfile
      #---------------- Insert chosen wake up action code here ----------------
      }
      else {
      echo "$mydate - PID: $nid - No such process, exiting watcher." | out-file -Append $logfile
      

      }

    5. Open task scheduler as admin and create the "Idle" task;

      • On the general tab, choose to "change user or group" that the task is run as.
      • In the "Select user or group" window, click the advanced button, then "find now".
      • Scroll down to find the "SYSTEM" account, click once to highlight, then click OK.
      • Click OK again.
      • Switch to the triggers tab and create a one time trigger a few minutes in the future.
      • Under advanced settings, check the box to "Repeat task every:" and then type into the box "1 minute", and change the "for a duration of" to indefinitely.
      • Switch to the actions tab and add a new action;
      • The "program/script" box should contain the path to your powershell.exe that you copied to the scripts folder earlier.
      • Add the following arguments, replacing the file path with your own:

        -ExecutionPolicy Bypass -file "C:\scripts\idle.ps1"

      • Go to the conditions tab and check the box to only start if idle, setting the idle time to your chosen time out.

      • Check the other two boxes under the idle section "Stop if the computer ceases to be idle", and "Restart if the idle state resume".
      • Click "OK" to save and close the scheduled task.

    Hope someone finds this useful!

    Tim