added logging to the project

This commit is contained in:
2026-03-27 12:30:30 -07:00
parent 42e20da6de
commit 989426efa0
5 changed files with 77 additions and 2 deletions

View File

@@ -55,6 +55,7 @@ Edit `config.psd1` before deploying:
| Key | Description | Default | | Key | Description | Default |
|---|---|---| |---|---|---|
| `UNCPath` | Base UNC path for clip storage — username subfolder created automatically | `\\server\ITCaptures` | | `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` | | `BufferSeconds` | Replay buffer duration in seconds | `120` |
| `WebSocketPort` | OBS WebSocket port — must match `obs-config/plugin_config/obs-websocket/config.json` | `4455` | | `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` | | `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 - 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) - A Windows toast notification confirms success or failure (falls back to a message box if toast is unavailable)
- Clips appear at `\\server\ITCaptures\<username>\` named by timestamp - Clips appear at `\\server\ITCaptures\<username>\` named by timestamp
- Logs are written to `\\server\ITLogs\<username>\` — 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 ## Changing the Buffer Duration

View File

@@ -2,6 +2,10 @@
# Base UNC path for saved clips — a subfolder per username is created automatically # Base UNC path for saved clips — a subfolder per username is created automatically
UNCPath = '\\server\ITCaptures' 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) # Replay buffer duration in seconds (120 = 2 minutes)
BufferSeconds = 120 BufferSeconds = 120

View File

@@ -14,11 +14,22 @@ param(
$ErrorActionPreference = 'SilentlyContinue' $ErrorActionPreference = 'SilentlyContinue'
if ($Port -eq 0) {
$config = Import-PowerShellDataFile -Path (Join-Path $PSScriptRoot '..\config.psd1') $config = Import-PowerShellDataFile -Path (Join-Path $PSScriptRoot '..\config.psd1')
if ($Port -eq 0) {
$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 $ws = $null
$cts = $null $cts = $null
@@ -28,34 +39,43 @@ try {
$uri = [System.Uri]"ws://localhost:$Port" $uri = [System.Uri]"ws://localhost:$Port"
$ws.ConnectAsync($uri, $cts.Token).Wait() $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 $buffer = New-Object byte[] 8192
# Receive Hello (opcode 0) # Receive Hello (opcode 0)
$null = $ws.ReceiveAsync($buffer, $cts.Token).Result $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 # Send Identify (opcode 1) — no authentication
$identify = [System.Text.Encoding]::UTF8.GetBytes('{"op":1,"d":{"rpcVersion":1}}') $identify = [System.Text.Encoding]::UTF8.GetBytes('{"op":1,"d":{"rpcVersion":1}}')
$ws.SendAsync($identify, [System.Net.WebSockets.WebSocketMessageType]::Text, $true, $cts.Token).Wait() $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) # Receive Identified (opcode 2)
$null = $ws.ReceiveAsync($buffer, $cts.Token).Result $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) # Send SaveReplayBuffer request (opcode 6)
$request = [System.Text.Encoding]::UTF8.GetBytes('{"op":6,"d":{"requestType":"SaveReplayBuffer","requestId":"itrecord-1"}}') $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() $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) # Receive RequestResponse (opcode 7)
$null = $ws.ReceiveAsync($buffer, $cts.Token).Result $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() $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 return $true
} }
catch { catch {
Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [ERROR] Save failed: $_"
return $false return $false
} }
finally { finally {
if ($ws) { $ws.Dispose() } if ($ws) { $ws.Dispose() }
if ($cts) { $cts.Dispose() } if ($cts) { $cts.Dispose() }
Stop-Transcript -ErrorAction SilentlyContinue
} }

View File

@@ -12,6 +12,18 @@
Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing 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 { function Show-Notification {
param([string]$Title, [string]$Body) param([string]$Title, [string]$Body)
try { try {
@@ -46,12 +58,16 @@ $saveItem.Add_Click({
$saveItem.Enabled = $false $saveItem.Enabled = $false
$saveItem.Text = 'Saving...' $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 $result = & powershell.exe -ExecutionPolicy Bypass -NonInteractive -File $saveScript
if ($result -eq $true) { 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.' Show-Notification -Title 'IT Screen Recorder' -Body 'Replay saved.'
} }
else { 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.' 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({ $exitItem.Add_Click({
Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Tray icon exited by user."
$tray.Visible = $false $tray.Visible = $false
[System.Windows.Forms.Application]::Exit() [System.Windows.Forms.Application]::Exit()
}) })
@@ -74,3 +91,4 @@ $tray.ContextMenuStrip = $menu
[System.Windows.Forms.Application]::Run() [System.Windows.Forms.Application]::Run()
$tray.Dispose() $tray.Dispose()
Stop-Transcript -ErrorAction SilentlyContinue

View File

@@ -15,6 +15,17 @@ $ErrorActionPreference = 'Stop'
$configPath = Join-Path $PSScriptRoot '..\config.psd1' $configPath = Join-Path $PSScriptRoot '..\config.psd1'
$config = Import-PowerShellDataFile -Path $configPath $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 --- # --- Verify required project files are accessible ---
$requiredPaths = @( $requiredPaths = @(
(Join-Path $PSScriptRoot '..\obs-config\global.ini') (Join-Path $PSScriptRoot '..\obs-config\global.ini')
@@ -24,12 +35,17 @@ $requiredPaths = @(
) )
foreach ($path in $requiredPaths) { foreach ($path in $requiredPaths) {
if (-not (Test-Path -Path $path)) { 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 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) --- # --- Skip if OBS is already running (handles reconnect scenarios) ---
if (Get-Process -Name 'obs64' -ErrorAction SilentlyContinue) { 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 exit 0
} }
@@ -37,6 +53,9 @@ if (Get-Process -Name 'obs64' -ErrorAction SilentlyContinue) {
$userCapturePath = Join-Path $config.UNCPath $env:USERNAME $userCapturePath = Join-Path $config.UNCPath $env:USERNAME
if (-not (Test-Path -Path $userCapturePath)) { if (-not (Test-Path -Path $userCapturePath)) {
New-Item -ItemType Directory -Path $userCapturePath -Force | Out-Null 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 --- # --- Detect primary monitor resolution ---
@@ -44,6 +63,7 @@ Add-Type -AssemblyName System.Windows.Forms
$screen = [System.Windows.Forms.Screen]::PrimaryScreen $screen = [System.Windows.Forms.Screen]::PrimaryScreen
$width = $screen.Bounds.Width $width = $screen.Bounds.Width
$height = $screen.Bounds.Height $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 --- # --- Deploy global OBS config and WebSocket plugin config ---
$obsConfigRoot = "$env:APPDATA\obs-studio" $obsConfigRoot = "$env:APPDATA\obs-studio"
@@ -55,6 +75,8 @@ $wsConfigDir = "$obsConfigRoot\plugin_config\obs-websocket"
New-Item -ItemType Directory -Path $wsConfigDir -Force | Out-Null New-Item -ItemType Directory -Path $wsConfigDir -Force | Out-Null
Copy-Item -Path "$sourceConfig\plugin_config\obs-websocket\config.json" -Destination "$wsConfigDir\config.json" -Force 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) --- # --- Write OBS profile (basic.ini) ---
$profileDir = "$env:APPDATA\obs-studio\basic\profiles\$($config.ProfileName)" $profileDir = "$env:APPDATA\obs-studio\basic\profiles\$($config.ProfileName)"
New-Item -ItemType Directory -Path $profileDir -Force | Out-Null New-Item -ItemType Directory -Path $profileDir -Force | Out-Null
@@ -88,6 +110,8 @@ ColorSpace=709
ColorRange=Partial ColorRange=Partial
"@ | Set-Content -Path "$profileDir\basic.ini" -Encoding UTF8 "@ | 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 --- # --- Launch OBS hidden ---
$obsArgs = @( $obsArgs = @(
'--minimize-to-tray' '--minimize-to-tray'
@@ -100,6 +124,7 @@ $obsArgs = @(
) )
Start-Process -FilePath $config.OBSExecutable -ArgumentList $obsArgs -WindowStyle Hidden 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 --- # --- Launch tray icon as a separate background process ---
$trayScript = Join-Path $PSScriptRoot 'Show-ReplayTray.ps1' $trayScript = Join-Path $PSScriptRoot 'Show-ReplayTray.ps1'
@@ -109,3 +134,6 @@ Start-Process -FilePath 'powershell.exe' -ArgumentList @(
'-WindowStyle', 'Hidden' '-WindowStyle', 'Hidden'
'-File', $trayScript '-File', $trayScript
) -WindowStyle Hidden ) -WindowStyle Hidden
Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [INFO] Tray icon launched."
Stop-Transcript -ErrorAction SilentlyContinue