|  | @@ -0,0 +1,89 @@
 | 
	
		
			
				|  |  | +# onShutdown.ps1
 | 
	
		
			
				|  |  | +#
 | 
	
		
			
				|  |  | +# for Windows 10
 | 
	
		
			
				|  |  | +# - sends an MQTT message on Shutdown and a different one on Restart
 | 
	
		
			
				|  |  | +# - intended to switch off a Tasmota plug, delayed, after shutdown, but NOT on restart
 | 
	
		
			
				|  |  | +#
 | 
	
		
			
				|  |  | +# Prerequisites:
 | 
	
		
			
				|  |  | +# - download Mosquitto Windows x64 installer
 | 
	
		
			
				|  |  | +# - extract and copy mosquitto_pub.exe, mosquitto.dll, libssl-1_1-x64.dll and libcrypto-1_1-x64.dll to
 | 
	
		
			
				|  |  | +#   c:\Tools\mosquitto (or anywhere and change $mosquittoPubPath accordingly)
 | 
	
		
			
				|  |  | +#
 | 
	
		
			
				|  |  | +# This script checks if there is a Event 1074 (source: User32) in the System Event Log, that is
 | 
	
		
			
				|  |  | +# less than 15 seconds old. 
 | 
	
		
			
				|  |  | +# If so, it checks the content of this event, which contains the info if we are about to 
 | 
	
		
			
				|  |  | +# "power off" or "restart". 
 | 
	
		
			
				|  |  | +#
 | 
	
		
			
				|  |  | +# The script must be set as shutdown script via Windows Group Policy (local GPO)
 | 
	
		
			
				|  |  | +# Setup: Start -> Run -> gpedit.msc
 | 
	
		
			
				|  |  | +#   -> Computer Configuration -> Windows Settings -> Scripts (Startup/Shutdown) -> Shutdown
 | 
	
		
			
				|  |  | +#   -> there, go to tab "PowerShell Scripts" and simply browse for this script. 
 | 
	
		
			
				|  |  | +#      Group Policy service seems to handle the PS Execution-Policy, 
 | 
	
		
			
				|  |  | +#      so that it does not have to be set to unrestricted system-wide. 
 | 
	
		
			
				|  |  | +#      I saved the script to C:\scripts\onShutdown.ps1
 | 
	
		
			
				|  |  | +#
 | 
	
		
			
				|  |  | +# Starting it via Task Scheduler on Event 1074 unfortunately does not work, as the script 
 | 
	
		
			
				|  |  | +# is getting killed before it actually has done anything most times. 
 | 
	
		
			
				|  |  | +# Via Group Policy, the shutdown will be delayed until the script has finished its work. 
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +$logFile = "C:\LOG\onShutdown_PS.log"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +$mosquittoPubPath = "c:\Tools\mosquitto\mosquitto_pub.exe"
 | 
	
		
			
				|  |  | +$mqttHost = "mqtt.lan"
 | 
	
		
			
				|  |  | +#$mqttUser = "username"
 | 
	
		
			
				|  |  | +#$mqttPwd = "password"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +# Topic to send status info to (SHUTDOWN or RESTART)
 | 
	
		
			
				|  |  | +$mqttStatTopic = "MediaPC/ShutdownEvent"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +# Topic/Payload on Shutdown (i.E. send an Event to a Tasmota device)
 | 
	
		
			
				|  |  | +$mqttTopicOnShutdown = "cmnd/TasmotaMediaPC/event"
 | 
	
		
			
				|  |  | +$mqttPayloadOnShutdown = "delayedOff"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +# Topic/Payload on Restart (i.E. send an Event to a Tasmota device)
 | 
	
		
			
				|  |  | +#$mqttTopicOnRestart = ""
 | 
	
		
			
				|  |  | +#$mqttPayloadOnRestart = ""
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +###########
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +$mosquittoPubUserPassword = ""
 | 
	
		
			
				|  |  | +if($mqttUser -and $mqttPwd -and $mqttUser -ne "" -and $mqttPwd -ne "") {
 | 
	
		
			
				|  |  | +	$mosquittoPubUserPassword = "-u $mqttUser -P $mqttPwd "
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +$logDate = "{0:yyyy-MM-dd HH:mm:ss}" -f (Get-Date)
 | 
	
		
			
				|  |  | +if($logFile) { Write-Output $logDate >> $logFile }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Get-WinEvent -FilterHashtable @{logname='System'; id=1074} -MaxEvents 1 | ForEach-Object {
 | 
	
		
			
				|  |  | +    $ts_event = [datetime]$_.TimeCreated
 | 
	
		
			
				|  |  | +    $ts_delta = (New-TimeSpan -Start $ts_event).TotalSeconds
 | 
	
		
			
				|  |  | +    $ts_str = $ts_delta.ToString("#")
 | 
	
		
			
				|  |  | +	$command = $_.Properties[4].Value
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    if($logFile) { Write-Output "  last shutdown-event was '$command', $ts_str s ago" >> $logFile }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if($ts_delta -lt 15) {
 | 
	
		
			
				|  |  | +		if($logFile) { Write-Output "    ==> OK, publish MQTT messages." >> $logFile }
 | 
	
		
			
				|  |  | +        if($command -eq "power off") {
 | 
	
		
			
				|  |  | +			$cmdLine = "$mosquittoPubPath -h $mqttHost $mosquittoPubUserPassword-t $mqttStatTopic -m SHUTDOWN"
 | 
	
		
			
				|  |  | +			Invoke-Expression $cmdLine
 | 
	
		
			
				|  |  | +			if($mqttTopicOnShutdown -and $mqttTopicOnShutdown -ne "") {
 | 
	
		
			
				|  |  | +				$cmdLine = "$mosquittoPubPath -h $mqttHost $mosquittoPubUserPassword-t $mqttTopicOnShutdown -m $mqttPayloadOnShutdown"
 | 
	
		
			
				|  |  | +				Invoke-Expression $cmdLine
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        elseif($command -eq "restart") {
 | 
	
		
			
				|  |  | +			$cmdLine = "$mosquittoPubPath -h $mqttHost $mosquittoPubUserPassword-t $mqttStatTopic -m RESTART"
 | 
	
		
			
				|  |  | +			Invoke-Expression $cmdLine
 | 
	
		
			
				|  |  | +			if($mqttTopicOnRestart -and $mqttTopicOnRestart -ne "") {
 | 
	
		
			
				|  |  | +				$cmdLine = "$mosquittoPubPath -h $mqttHost $mosquittoPubUserPassword-t $mqttTopicOnRestart -m $mqttPayloadOnRestart"
 | 
	
		
			
				|  |  | +				Invoke-Expression $cmdLine
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    else {
 | 
	
		
			
				|  |  | +        if($logFile) { Write-Output "    ==> too old. Nothing to do." >> $logFile }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 |