# GSP Windows Agent Updater - PowerShell Script # This script updates an existing Git-managed agent installation #Requires -RunAsAdministrator param( [string]$InstallPath = "C:\GSP", [string]$GitBranch = "master" ) $Script:AgentDir = Join-Path $InstallPath "Agent" $Script:GitDir = Join-Path $InstallPath "tools\PortableGit" $Script:BackupDir = Join-Path $InstallPath "backups\agent" $Script:LogsDir = Join-Path $InstallPath "logs" $Script:UpdateLogFile = Join-Path $Script:LogsDir "update.log" function Log-Message { param([string]$Message, [switch]$IsError = $false) $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $logLine = "[$timestamp] $Message" if ($IsError) { Write-Host $logLine -ForegroundColor Red } else { Write-Host $logLine } Add-Content -Path $Script:UpdateLogFile -Value $logLine -Force } function Test-Administrator { $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object Security.Principal.WindowsPrincipal($currentUser) return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } function Stop-Agent { Log-Message "Stopping agent..." try { # Try to stop the scheduled task Stop-ScheduledTask -TaskName "GSP Windows Agent" -ErrorAction SilentlyContinue Log-Message "Scheduled task stopped" # Give it a moment to shut down gracefully Start-Sleep -Seconds 2 # Kill any remaining bash/perl processes from the agent Get-Process bash,perl -ErrorAction SilentlyContinue | ForEach-Object { try { Stop-Process -Id $_.Id -Force -ErrorAction SilentlyContinue Log-Message "Killed remaining process: $($_.Name) (PID: $($_.Id))" } catch { # Process may already be gone } } return $true } catch { Log-Message "WARNING stopping agent: $_" -IsError $true return $false } } function Backup-Agent { Log-Message "Backing up current agent..." try { $backupName = "agent-backup-$(Get-Date -Format 'yyyyMMdd-HHmmss')" $backupPath = Join-Path $Script:BackupDir $backupName Log-Message "Backup destination: $backupPath" Copy-Item -Path $Script:AgentDir -Destination $backupPath -Recurse -Force Log-Message "Backup completed successfully" return $backupPath } catch { Log-Message "ERROR creating backup: $_" -IsError $true return $null } } function Preserve-LocalFolders { Log-Message "Preserving local configuration and runtime folders..." $preserved = @{} $preserveFolders = @("Cfg", "steamcmd", "screenlogs", "startups", "tmp", "shared") try { foreach ($folder in $preserveFolders) { $folderPath = Join-Path $Script:AgentDir $folder if (Test-Path $folderPath) { $tempPath = Join-Path $env:TEMP "gsp_preserve_$folder" if (Test-Path $tempPath) { Remove-Item $tempPath -Recurse -Force } Copy-Item -Path $folderPath -Destination $tempPath -Recurse -Force $preserved[$folder] = $tempPath Log-Message " Preserved: $folder" } } return $preserved } catch { Log-Message "ERROR preserving folders: $_" -IsError $true return @{} } } function Update-Repository { Log-Message "Updating repository from Git..." try { $gitExe = Join-Path $Script:GitDir "cmd\git.exe" if (-not (Test-Path $gitExe)) { Log-Message "ERROR: git.exe not found at: $gitExe" -IsError $true return $false } if (-not (Test-Path (Join-Path $Script:AgentDir ".git"))) { Log-Message "ERROR: Agent directory is not a Git repository (.git folder not found)" -IsError $true Log-Message "The agent must be installed with the Git-based installer to use this update script" return $false } Log-Message "Running git fetch..." $fetchProcess = Start-Process -FilePath $gitExe ` -ArgumentList "fetch", "origin" ` -Wait -PassThru -NoNewWindow -WorkingDirectory $Script:AgentDir if ($fetchProcess.ExitCode -ne 0) { Log-Message "ERROR: git fetch failed with code: $($fetchProcess.ExitCode)" -IsError $true return $false } Log-Message "Running git reset to $GitBranch..." $resetProcess = Start-Process -FilePath $gitExe ` -ArgumentList "reset", "--hard", "origin/$GitBranch" ` -Wait -PassThru -NoNewWindow -WorkingDirectory $Script:AgentDir if ($resetProcess.ExitCode -ne 0) { Log-Message "ERROR: git reset failed with code: $($resetProcess.ExitCode)" -IsError $true return $false } Log-Message "Repository updated successfully" return $true } catch { Log-Message "ERROR updating repository: $_" -IsError $true return $false } } function Restore-LocalFolders { param([hashtable]$PreservedFolders) Log-Message "Restoring preserved local folders..." try { foreach ($folder in $PreservedFolders.Keys) { $tempPath = $PreservedFolders[$folder] $targetPath = Join-Path $Script:AgentDir $folder if (Test-Path $targetPath) { Remove-Item -Path $targetPath -Recurse -Force } Copy-Item -Path $tempPath -Destination $targetPath -Recurse -Force Remove-Item -Path $tempPath -Recurse -Force Log-Message " Restored: $folder" } return $true } catch { Log-Message "ERROR restoring folders: $_" -IsError $true return $false } } function Validate-Agent { Log-Message "Validating agent syntax..." try { $agentScript = Join-Path $Script:AgentDir "OGP64\OGP\ogp_agent.pl" if (-not (Test-Path $agentScript)) { Log-Message "WARNING: ogp_agent.pl not found, skipping syntax check" return $true } # Try to run perl syntax check $perlCheck = Start-Process -FilePath "perl.exe" ` -ArgumentList "-c", $agentScript ` -Wait -PassThru -NoNewWindow -ErrorAction SilentlyContinue if ($perlCheck.ExitCode -ne 0) { Log-Message "WARNING: Perl syntax check failed, but update may still be valid" -IsError $true } else { Log-Message "Perl syntax validation passed" } return $true } catch { Log-Message "WARNING: Could not validate agent syntax: $_" -IsError $true return $true } } function Start-Agent { Log-Message "Starting agent..." try { Start-ScheduledTask -TaskName "GSP Windows Agent" -ErrorAction SilentlyContinue Log-Message "Scheduled task started" return $true } catch { Log-Message "WARNING: Could not start scheduled task immediately" -IsError $true Log-Message "Agent will start at next system boot" return $true } } function Rollback-Update { param([string]$BackupPath) Log-Message "ROLLING BACK UPDATE..." if (-not (Test-Path $BackupPath)) { Log-Message "ERROR: Backup not found, cannot rollback" -IsError $true return $false } try { Log-Message "Restoring from backup: $BackupPath" # Stop agent first Stop-Agent | Out-Null # Remove updated directory if (Test-Path $Script:AgentDir) { Remove-Item -Path $Script:AgentDir -Recurse -Force } # Restore backup Copy-Item -Path $BackupPath -Destination $Script:AgentDir -Recurse -Force # Restart agent Start-Agent | Out-Null Log-Message "Rollback completed successfully" return $true } catch { Log-Message "ERROR during rollback: $_" -IsError $true return $false } } function Main { Log-Message "=========================================" Log-Message "GSP Windows Agent Update" Log-Message "=========================================" Log-Message "Install Path: $InstallPath" Log-Message "Git Branch: $GitBranch" Log-Message "" # Check admin if (-not (Test-Administrator)) { Log-Message "ERROR: This script must be run as Administrator" -IsError $true exit 1 } # Verify directories exist if (-not (Test-Path $Script:AgentDir)) { Log-Message "ERROR: Agent not found at: $Script:AgentDir" -IsError $true exit 1 } if (-not (Test-Path $Script:GitDir)) { Log-Message "ERROR: Portable Git not found at: $Script:GitDir" -IsError $true exit 1 } # Create logs directory if needed if (-not (Test-Path $Script:LogsDir)) { New-Item -ItemType Directory -Path $Script:LogsDir -Force | Out-Null } # Stop agent Stop-Agent # Create backup $backupPath = Backup-Agent if (-not $backupPath) { Log-Message "FATAL: Could not create backup" -IsError $true exit 1 } # Preserve local folders $preserved = Preserve-LocalFolders # Update from Git if (-not (Update-Repository)) { Log-Message "FATAL: Update failed, rolling back..." -IsError $true Rollback-Update $backupPath | Out-Null exit 1 } # Restore preserved folders if ($preserved.Count -gt 0) { if (-not (Restore-LocalFolders $preserved)) { Log-Message "WARNING: Failed to restore all folders" -IsError $true Rollback-Update $backupPath | Out-Null exit 1 } } # Validate agent Validate-Agent # Start agent Start-Agent Log-Message "" Log-Message "=========================================" Log-Message "Update Complete!" Log-Message "=========================================" Log-Message "Agent has been updated successfully" Log-Message "Backup location: $backupPath" Log-Message "Log file: $Script:UpdateLogFile" Log-Message "" Log-Message "The agent will restart at the next opportunity" Log-Message "" Read-Host "Press Enter to close this window" } Main