From 4bfed036217d4869de6d7e8d74126a94bec72d97 Mon Sep 17 00:00:00 2001 From: Derek Cooper Date: Mon, 30 Mar 2026 10:38:35 -0700 Subject: [PATCH] Added WPF popups and timeouts so it doesn't break at Logon if App Volumes has attached yet. --- config.psd1 | 3 + scripts/Invoke-ReplaySave.ps1 | 106 ++++++++++++++++++- scripts/Show-ReplayTray.ps1 | 2 +- scripts/Start-OBSReplayBuffer.ps1 | 164 +++++++++++++++++++++++++++++- 4 files changed, 267 insertions(+), 8 deletions(-) diff --git a/config.psd1 b/config.psd1 index 68d16db..16482ae 100644 --- a/config.psd1 +++ b/config.psd1 @@ -18,4 +18,7 @@ # Must match the profile folder name and scene collection filename ProfileName = 'ITMonitor' SceneCollection = 'ITMonitor' + + # IT helpdesk contact number shown in the startup notification + ITContactNumber = '555-555-5555' } diff --git a/scripts/Invoke-ReplaySave.ps1 b/scripts/Invoke-ReplaySave.ps1 index c36f1b6..28bbbd0 100644 --- a/scripts/Invoke-ReplaySave.ps1 +++ b/scripts/Invoke-ReplaySave.ps1 @@ -23,7 +23,7 @@ if ($Port -eq 0) { try { $logDir = [System.Environment]::ExpandEnvironmentVariables($config.LogPath) New-Item -ItemType Directory -Path $logDir -Force -ErrorAction SilentlyContinue | Out-Null - Start-Transcript -Path (Join-Path $logDir 'OBSReplayBuffer-Save.log') -Append -ErrorAction Stop + Start-Transcript -Path (Join-Path $logDir 'OBSReplayBuffer-Save.log') -Force -ErrorAction Stop } catch { # Log path unavailable — continue without transcript } @@ -57,6 +57,7 @@ try { Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Received Identified (op 2)." # Send SaveReplayBuffer request (opcode 6) + $saveRequestTime = Get-Date $request = [System.Text.Encoding]::UTF8.GetBytes('{"op":6,"d":{"requestType":"SaveReplayBuffer","requestId":"itrecord-1"}}') $ws.SendAsync($request, [System.Net.WebSockets.WebSocketMessageType]::Text, $true, $cts.Token).Wait() Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Sent SaveReplayBuffer request (op 6)." @@ -71,7 +72,108 @@ try { } $ws.CloseAsync([System.Net.WebSockets.WebSocketCloseStatus]::NormalClosure, 'Done', $cts.Token).Wait() - Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] WebSocket closed. Save completed successfully." + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] WebSocket closed." + + # --- Verify replay file was written to disk --- + $captureDir = Join-Path $config.UNCPath $env:USERNAME + $fileTimeout = [datetime]::UtcNow.AddSeconds(30) + $savedFile = $null + while (-not $savedFile) { + if ([datetime]::UtcNow -ge $fileTimeout) { + throw "OBS accepted the save request but no replay file appeared in '$captureDir' within 30 seconds." + } + $savedFile = Get-ChildItem -Path $captureDir -Filter '*.mkv' -ErrorAction SilentlyContinue | + Where-Object { $_.LastWriteTime -ge $saveRequestTime } | + Sort-Object LastWriteTime -Descending | + Select-Object -First 1 + if (-not $savedFile) { Start-Sleep -Seconds 2 } + } + $fileSizeMB = [math]::Round($savedFile.Length / 1MB, 2) + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Replay file confirmed: $($savedFile.FullName) ($fileSizeMB MB)" + + # --- Notify user that the replay was saved --- + $notifyScript = { + param($fileName, $fileSizeMB, $contactNumber) + + Add-Type -AssemblyName PresentationFramework + Add-Type -AssemblyName WindowsBase + Add-Type -AssemblyName System.Drawing + + $hBitmap = [System.Drawing.SystemIcons]::Shield.ToBitmap().GetHbitmap() + $wpfImage = [System.Windows.Interop.Imaging]::CreateBitmapSourceFromHBitmap( + $hBitmap, [IntPtr]::Zero, [System.Windows.Int32Rect]::Empty, + [System.Windows.Media.Imaging.BitmapSizeOptions]::FromEmptyOptions() + ) + [System.Runtime.InteropServices.Marshal]::DeleteObject($hBitmap) + + [xml]$xaml = @" + + + + + + + + + + + + + + +