windowsscriptdeck.sdPlugin/StartPlugin.ps1
# Set up a log path for this plugin instance (make it based off of the starttime) $global:STREAMDECK_PLUGINLOGPATH = $logPath = Join-Path $psScriptRoot ( ([Datetime]::Now.ToString('o').replace(':','.') -replace '\.\d+(?=[+-])') + '.log' ) "Log Started @ $([DateTime]::Now.ToString('s')). Running under process ID $($pid)" | Add-Content -Path $logPath # Put each named argument into a dictionary. $argObject = [Ordered]@{} for ($i = 0; $i -lt $args.Length; $i+=2 ) # We do this by going in twos thru the arguments { $k = $args[$i].TrimStart('-') # removing the - from the key $v = $args[$i + 1] $argObject[$k] = if ("$v".StartsWith('{')) { # and converting any JSON-like input. $v | ConvertFrom-Json } else { $v } } $Host.UI.RawUI.WindowTitle = "StreamDeck $pid" # Once we've collected an arguments dictionary, turn it into an object, $argObject = [PSCustomObject]$argObject $argObject | ConvertTo-Json | # convert it to JSON, Add-Content -Path $logPath # and add it to the log. # Now let's register the functions we need. # |Function|Purpose | # |--------|--------------------------------------------------| # |Send-StreamDeck |Sends messages to the StreamDeck | . $psScriptRoot\Send-StreamDeck.ps1 # |Receive-StreamDeck |Receives messages from the StreamDeck | . $psScriptRoot\Receive-StreamDeck.ps1 # We will want to declare a few globals to keep track of state. if (-not $Global:STREAMDECK_DEVICES) { $Global:STREAMDECK_DEVICES = @{} } if (-not $Global:STREAMDECK_BUTTONS) { $Global:STREAMDECK_BUTTONS = @{} } if (-not $global:STREAMDECK_SETTINGS) { $global:STREAMDECK_SETTINGS = @{} } $localFiles = Get-ChildItem -Path $psScriptRoot -Filter *.ps1 $heartbeatTimer = [Timers.Timer]::new() $heartbeatTimer.Interval = [Timespan]::FromMinutes(10).totalmilliseconds $heartbeatTimer.AutoReset = $true $heartbeatTimer.Start() Register-ObjectEvent -InputObject $heartbeatTimer -EventName Elapsed -Action { "Heartbeat @ $([DateTime]::Now.ToString('s'))" | Add-Content -Path $global:STREAMDECK_PLUGINLOGPATH } foreach ($file in @( $localFiles | Where-Object Name -Like '*.handler.ps1' $localFiles | Where-Object Name -Like 'On_*.ps1' )) { $scriptFile = $ExecutionContext.SessionState.InvokeCommand.GetCommand($file.Fullname, 'ExternalScript') $sourceIdentifier = $file.Name -replace '^On_' -replace '\.ps1$' -replace '\.handler$' Add-Content -Path $logPath -value "Registering Handler for '$sourceIdentifier': $($file.fullname)" $actionScriptBlock = [ScriptBlock]::Create(" try { . '$($file.Fullname)' } catch { `$err = `$_ `$errorString = `$err | Out-String `$errorString | Add-Content -Path `$global:STREAMDECK_PLUGINLOGPATH Start-Job -ScriptBlock { (New-Object -ComObject WScript.Shell).Popup(`"`$args`",0,`"`StreamDeck - ProcessID: `$pid`", 16) } -ArgumentList `$errorString } ") Register-EngineEvent -SourceIdentifier $sourceIdentifier -Action $actionScriptBlock } do { "Starting Watching Streamdeck @ $([DateTime]::Now.ToString('s'))" | Add-Content -Path $logPath $argObject | Receive-StreamDeck -OutputType Message 2>&1 | Foreach-Object { if ($Global:STREAMDECK_WEBSOCKET.State -in 'Aborted' ,'CloseReceived') { $_ | Out-String | Add-Content -Path $logPath break } $_ | Out-String | Add-Content -Path $logPath } if ($Global:STREAMDECK_WEBSOCKET.State -in 'Aborted' ,'CloseReceived') { break } $sleepTime = (Get-Random -Minimum 30 -Maximum 180) "Finished Watching Streamdeck @ $([DateTime]::Now.ToString('s')). Trying again in $($sleepTime)" | Add-Content -Path $logPath Start-Sleep -Seconds $sleepTime } while ($true) "Log Stopped @ $([DateTime]::Now.ToString('s')). Running under process ID $($pid)" | Add-Content -Path $logPath |