onShutdown.ps1 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. # onShutdown.ps1
  2. #
  3. # for Windows 10
  4. # - sends an MQTT message on Shutdown and a different one on Restart
  5. # - intended to switch off a Tasmota plug, delayed, after shutdown, but NOT on restart
  6. #
  7. # Prerequisites:
  8. # - download Mosquitto Windows x64 installer
  9. # - extract and copy mosquitto_pub.exe, mosquitto.dll, libssl-1_1-x64.dll and libcrypto-1_1-x64.dll to
  10. # c:\Tools\mosquitto (or anywhere and change $mosquittoPubPath accordingly)
  11. # - Windows Update PowerShell Module:
  12. # http://woshub.com/pswindowsupdate-module/
  13. # (as Admin): Install-Module -Name PSWindowsUpdate
  14. #
  15. # This script checks if there is a Event 1074 (source: User32) in the System Event Log, that is
  16. # less than 15 seconds old.
  17. # If so, it checks the content of this event, which contains the info if we are about to
  18. # "power off" or "restart".
  19. #
  20. # The script must be set as shutdown script via Windows Group Policy (local GPO)
  21. # Setup: Start -> Run -> gpedit.msc
  22. # -> Computer Configuration -> Windows Settings -> Scripts (Startup/Shutdown) -> Shutdown
  23. # -> there, go to tab "PowerShell Scripts" and simply browse for this script.
  24. # Group Policy service seems to handle the PS Execution-Policy,
  25. # so that it does not have to be set to unrestricted system-wide.
  26. # I saved the script to C:\scripts\onShutdown.ps1
  27. #
  28. # Starting it via Task Scheduler on Event 1074 unfortunately does not work, as the script
  29. # is getting killed before it actually has done anything most times.
  30. # Via Group Policy, the shutdown will be delayed until the script has finished its work.
  31. $logFile = "C:\LOG\onShutdown_PS.log"
  32. $mosquittoPubPath = "c:\Tools\mosquitto\mosquitto_pub.exe"
  33. $mqttHost = "mqtt.lan"
  34. $mqttUser = "script"
  35. $mqttPwd = "rlAzqusqfbAy"
  36. # Topic to send status info to (SHUTDOWN or RESTART)
  37. $mqttStatTopic = "MediaPC-SZ/ShutdownEvent"
  38. # Topic/Payload on Shutdown (i.E. send an Event to a Tasmota device)
  39. $mqttTopicOnShutdown = "cmnd/T5SZ-Media-Pwr/event"
  40. $mqttPayloadOnShutdown = "delayedOff"
  41. # Topic/Payload on Restart (i.E. send an Event to a Tasmota device)
  42. #$mqttTopicOnRestart = ""
  43. #$mqttPayloadOnRestart = ""
  44. ###########
  45. $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
  46. $mosquittoPubUserPassword = ""
  47. if($mqttUser -and $mqttPwd -and $mqttUser -ne "" -and $mqttPwd -ne "") {
  48. $mosquittoPubUserPassword = "-u $mqttUser -P $mqttPwd "
  49. }
  50. $logDate = "{0:yyyy-MM-dd HH:mm:ss}" -f (Get-Date)
  51. if($logFile) { Write-Output $logDate >> $logFile }
  52. $WURebootRequired = Get-WURebootStatus.RebootRequired
  53. Get-WinEvent -FilterHashtable @{logname='System'; id=1074} -MaxEvents 1 | ForEach-Object {
  54. $ts_event = [datetime]$_.TimeCreated
  55. $ts_delta = (New-TimeSpan -Start $ts_event).TotalSeconds
  56. $ts_str = $ts_delta.ToString("#")
  57. $command = $_.Properties[4].Value
  58. if($logFile) {
  59. Write-Output " last shutdown-event was '$command', $ts_str s ago" >> $logFile
  60. if($WURebootRequired) {
  61. Write-Output " Windows Update reboot is required. As in this case the update will install on shutdown, Powerdown-Command to Tasmota is omitted this time." >> $logFile
  62. }
  63. }
  64. if($ts_delta -lt 15) {
  65. if($logFile) { Write-Output " ==> OK, publish MQTT messages." >> $logFile }
  66. if($command -eq "power off") {
  67. $cmdLine = "$mosquittoPubPath -h $mqttHost $mosquittoPubUserPassword-t $mqttStatTopic -m SHUTDOWN"
  68. Invoke-Expression $cmdLine
  69. if(-not $WURebootRequired -and $mqttTopicOnShutdown -and $mqttTopicOnShutdown -ne "") {
  70. $cmdLine = "$mosquittoPubPath -h $mqttHost $mosquittoPubUserPassword-t $mqttTopicOnShutdown -m $mqttPayloadOnShutdown"
  71. Invoke-Expression $cmdLine
  72. }
  73. }
  74. elseif($command -eq "restart") {
  75. $cmdLine = "$mosquittoPubPath -h $mqttHost $mosquittoPubUserPassword-t $mqttStatTopic -m RESTART"
  76. Invoke-Expression $cmdLine
  77. if($mqttTopicOnRestart -and $mqttTopicOnRestart -ne "") {
  78. $cmdLine = "$mosquittoPubPath -h $mqttHost $mosquittoPubUserPassword-t $mqttTopicOnRestart -m $mqttPayloadOnRestart"
  79. Invoke-Expression $cmdLine
  80. }
  81. }
  82. }
  83. else {
  84. if($logFile) { Write-Output " ==> too old. Nothing to do." >> $logFile }
  85. }
  86. }