diff --git a/README.md b/README.md index 7be8eb2..5a2637c 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ Edit `config.psd1` before deploying: | Key | Description | Default | |---|---|---| | `UNCPath` | Base UNC path for clip storage — username subfolder created automatically | `\\server\ITCaptures` | +| `LogPath` | Base UNC path for script logs — username subfolder created automatically; each script writes its own log file | `\\server\ITLogs` | | `BufferSeconds` | Replay buffer duration in seconds | `120` | | `WebSocketPort` | OBS WebSocket port — must match `obs-config/plugin_config/obs-websocket/config.json` | `4455` | | `OBSExecutable` | Full path to `obs64.exe` on the target machine | `C:\Program Files\obs-studio\bin\64bit\obs64.exe` | @@ -95,6 +96,10 @@ This is the only DEM task needed. The script handles all config file deployment, - Right-click the icon → **Save Replay** to save the last `BufferSeconds` of screen activity - A Windows toast notification confirms success or failure (falls back to a message box if toast is unavailable) - Clips appear at `\\server\ITCaptures\\` named by timestamp +- Logs are written to `\\server\ITLogs\\` — three files, one per script: + - `OBSReplayBuffer.log` — startup and config deployment + - `OBSReplayBuffer-Tray.log` — tray lifetime, save attempts, and results + - `OBSReplayBuffer-Save.log` — WebSocket steps for each save attempt ## Changing the Buffer Duration diff --git a/config.psd1 b/config.psd1 index 42294a4..636f258 100644 --- a/config.psd1 +++ b/config.psd1 @@ -2,6 +2,10 @@ # Base UNC path for saved clips — a subfolder per username is created automatically UNCPath = '\\server\ITCaptures' + # Base UNC path for script logs — a subfolder per username is created automatically + # Each script writes its own log: OBSReplayBuffer.log, OBSReplayBuffer-Tray.log, OBSReplayBuffer-Save.log + LogPath = '\\server\ITLogs' + # Replay buffer duration in seconds (120 = 2 minutes) BufferSeconds = 120 diff --git a/scripts/Invoke-ReplaySave.ps1 b/scripts/Invoke-ReplaySave.ps1 index d2dc332..8279b75 100644 --- a/scripts/Invoke-ReplaySave.ps1 +++ b/scripts/Invoke-ReplaySave.ps1 @@ -14,11 +14,22 @@ param( $ErrorActionPreference = 'SilentlyContinue' +$config = Import-PowerShellDataFile -Path (Join-Path $PSScriptRoot '..\config.psd1') if ($Port -eq 0) { - $config = Import-PowerShellDataFile -Path (Join-Path $PSScriptRoot '..\config.psd1') - $Port = $config.WebSocketPort + $Port = $config.WebSocketPort } +# --- Start transcript logging --- +try { + $logDir = Join-Path $config.LogPath $env:USERNAME + New-Item -ItemType Directory -Path $logDir -Force -ErrorAction SilentlyContinue | Out-Null + Start-Transcript -Path (Join-Path $logDir 'OBSReplayBuffer-Save.log') -Append -ErrorAction Stop +} catch { + # Log path unavailable — continue without transcript +} + +Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Invoke-ReplaySave started. Target: ws://localhost:$Port" + $ws = $null $cts = $null @@ -28,34 +39,43 @@ try { $uri = [System.Uri]"ws://localhost:$Port" $ws.ConnectAsync($uri, $cts.Token).Wait() + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] WebSocket connected." $buffer = New-Object byte[] 8192 # Receive Hello (opcode 0) $null = $ws.ReceiveAsync($buffer, $cts.Token).Result + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Received Hello (op 0)." # Send Identify (opcode 1) — no authentication $identify = [System.Text.Encoding]::UTF8.GetBytes('{"op":1,"d":{"rpcVersion":1}}') $ws.SendAsync($identify, [System.Net.WebSockets.WebSocketMessageType]::Text, $true, $cts.Token).Wait() + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Sent Identify (op 1)." # Receive Identified (opcode 2) $null = $ws.ReceiveAsync($buffer, $cts.Token).Result + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Received Identified (op 2)." # Send SaveReplayBuffer request (opcode 6) $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)." # Receive RequestResponse (opcode 7) $null = $ws.ReceiveAsync($buffer, $cts.Token).Result + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Received response (op 7)." $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." return $true } catch { + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [ERROR] Save failed: $_" return $false } finally { if ($ws) { $ws.Dispose() } if ($cts) { $cts.Dispose() } + Stop-Transcript -ErrorAction SilentlyContinue } diff --git a/scripts/Show-ReplayTray.ps1 b/scripts/Show-ReplayTray.ps1 index a9f02f2..c16d7b6 100644 --- a/scripts/Show-ReplayTray.ps1 +++ b/scripts/Show-ReplayTray.ps1 @@ -12,6 +12,18 @@ Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing +# --- Start transcript logging --- +try { + $config = Import-PowerShellDataFile -Path (Join-Path $PSScriptRoot '..\config.psd1') + $logDir = Join-Path $config.LogPath $env:USERNAME + New-Item -ItemType Directory -Path $logDir -Force -ErrorAction SilentlyContinue | Out-Null + Start-Transcript -Path (Join-Path $logDir 'OBSReplayBuffer-Tray.log') -Append -ErrorAction Stop +} catch { + # Log path unavailable — continue without transcript +} + +Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Tray icon started." + function Show-Notification { param([string]$Title, [string]$Body) try { @@ -46,12 +58,16 @@ $saveItem.Add_Click({ $saveItem.Enabled = $false $saveItem.Text = 'Saving...' + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Save replay requested." + $result = & powershell.exe -ExecutionPolicy Bypass -NonInteractive -File $saveScript if ($result -eq $true) { + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Replay saved successfully." Show-Notification -Title 'IT Screen Recorder' -Body 'Replay saved.' } else { + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [ERROR] Replay save failed." Show-Notification -Title 'IT Screen Recorder' -Body 'Could not save replay. Please contact the helpdesk.' } @@ -60,6 +76,7 @@ $saveItem.Add_Click({ }) $exitItem.Add_Click({ + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Tray icon exited by user." $tray.Visible = $false [System.Windows.Forms.Application]::Exit() }) @@ -74,3 +91,4 @@ $tray.ContextMenuStrip = $menu [System.Windows.Forms.Application]::Run() $tray.Dispose() +Stop-Transcript -ErrorAction SilentlyContinue diff --git a/scripts/Start-OBSReplayBuffer.ps1 b/scripts/Start-OBSReplayBuffer.ps1 index 5827842..b260763 100644 --- a/scripts/Start-OBSReplayBuffer.ps1 +++ b/scripts/Start-OBSReplayBuffer.ps1 @@ -15,6 +15,17 @@ $ErrorActionPreference = 'Stop' $configPath = Join-Path $PSScriptRoot '..\config.psd1' $config = Import-PowerShellDataFile -Path $configPath +# --- Start transcript logging --- +try { + $logDir = Join-Path $config.LogPath $env:USERNAME + New-Item -ItemType Directory -Path $logDir -Force -ErrorAction SilentlyContinue | Out-Null + Start-Transcript -Path (Join-Path $logDir 'OBSReplayBuffer.log') -Append -ErrorAction Stop +} catch { + # Log path unavailable — continue without transcript +} + +Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Starting OBS Replay Buffer for user: $env:USERNAME" + # --- Verify required project files are accessible --- $requiredPaths = @( (Join-Path $PSScriptRoot '..\obs-config\global.ini') @@ -24,12 +35,17 @@ $requiredPaths = @( ) foreach ($path in $requiredPaths) { if (-not (Test-Path -Path $path)) { + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [ERROR] Required path not accessible: $path" + Stop-Transcript -ErrorAction SilentlyContinue exit 1 } } +Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] All required paths verified." # --- Skip if OBS is already running (handles reconnect scenarios) --- if (Get-Process -Name 'obs64' -ErrorAction SilentlyContinue) { + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] OBS already running — exiting." + Stop-Transcript -ErrorAction SilentlyContinue exit 0 } @@ -37,6 +53,9 @@ if (Get-Process -Name 'obs64' -ErrorAction SilentlyContinue) { $userCapturePath = Join-Path $config.UNCPath $env:USERNAME if (-not (Test-Path -Path $userCapturePath)) { New-Item -ItemType Directory -Path $userCapturePath -Force | Out-Null + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Created capture folder: $userCapturePath" +} else { + Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Capture folder exists: $userCapturePath" } # --- Detect primary monitor resolution --- @@ -44,6 +63,7 @@ Add-Type -AssemblyName System.Windows.Forms $screen = [System.Windows.Forms.Screen]::PrimaryScreen $width = $screen.Bounds.Width $height = $screen.Bounds.Height +Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Detected resolution: ${width}x${height}" # --- Deploy global OBS config and WebSocket plugin config --- $obsConfigRoot = "$env:APPDATA\obs-studio" @@ -55,6 +75,8 @@ $wsConfigDir = "$obsConfigRoot\plugin_config\obs-websocket" New-Item -ItemType Directory -Path $wsConfigDir -Force | Out-Null Copy-Item -Path "$sourceConfig\plugin_config\obs-websocket\config.json" -Destination "$wsConfigDir\config.json" -Force +Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] OBS config files deployed to: $obsConfigRoot" + # --- Write OBS profile (basic.ini) --- $profileDir = "$env:APPDATA\obs-studio\basic\profiles\$($config.ProfileName)" New-Item -ItemType Directory -Path $profileDir -Force | Out-Null @@ -88,6 +110,8 @@ ColorSpace=709 ColorRange=Partial "@ | Set-Content -Path "$profileDir\basic.ini" -Encoding UTF8 +Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] OBS profile written: $profileDir\basic.ini" + # --- Launch OBS hidden --- $obsArgs = @( '--minimize-to-tray' @@ -100,6 +124,7 @@ $obsArgs = @( ) Start-Process -FilePath $config.OBSExecutable -ArgumentList $obsArgs -WindowStyle Hidden +Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] OBS launched: $($config.OBSExecutable)" # --- Launch tray icon as a separate background process --- $trayScript = Join-Path $PSScriptRoot 'Show-ReplayTray.ps1' @@ -109,3 +134,6 @@ Start-Process -FilePath 'powershell.exe' -ArgumentList @( '-WindowStyle', 'Hidden' '-File', $trayScript ) -WindowStyle Hidden +Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Tray icon launched." + +Stop-Transcript -ErrorAction SilentlyContinue