<# .SYNOPSIS ROA2WEB - Auto-Deploy Setup Wizard (Server-Side) .DESCRIPTION Interactive wizard to configure automatic deployment monitoring on Windows Server. Creates scheduled task that runs Check-And-Deploy.ps1 at specified intervals. .PARAMETER MonitorPath Path to monitor for deployment packages (default: C:\Temp) .PARAMETER ScriptsPath Path where Check-And-Deploy.ps1 is located (default: C:\Temp\ROA2WEB-Scripts) .PARAMETER CheckIntervalMinutes How often to check for new packages in minutes (default: 5) .PARAMETER AutoDeploy Automatically deploy new packages when found (default: true) .PARAMETER CreateScheduledTask Create Windows Scheduled Task for automation (default: true) .PARAMETER NonInteractive Run in non-interactive mode with provided parameters .EXAMPLE .\Setup-AutoDeploy.ps1 Launch interactive setup wizard .EXAMPLE .\Setup-AutoDeploy.ps1 -NonInteractive -MonitorPath "C:\Temp" -CheckIntervalMinutes 5 Non-interactive setup with defaults .NOTES Author: ROA2WEB Team Version: 1.0 (Auto-Deploy Setup) Requires: Administrator privileges, PowerShell 5.1+ #> [CmdletBinding()] param( [string]$MonitorPath = "C:\Temp", [string]$ScriptsPath = "C:\Temp\ROA2WEB-Scripts", [int]$CheckIntervalMinutes = 5, [bool]$AutoDeploy = $true, [bool]$CreateScheduledTask = $true, [switch]$NonInteractive ) $ErrorActionPreference = "Stop" # ============================================================================= # HELPER FUNCTIONS # ============================================================================= function Write-Step { param([string]$Message) Write-Host "`n[*] $Message" -ForegroundColor Cyan } function Write-Success { param([string]$Message) Write-Host " [OK] $Message" -ForegroundColor Green } function Write-Error { param([string]$Message) Write-Host " [ERROR] $Message" -ForegroundColor Red } function Write-Warning { param([string]$Message) Write-Host " [WARN] $Message" -ForegroundColor Yellow } function Write-Info { param([string]$Message) Write-Host " [*] $Message" -ForegroundColor Yellow } # ============================================================================= # WIZARD FUNCTIONS # ============================================================================= function Show-WizardWelcome { Clear-Host Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan Write-Host " ROA2WEB - Auto-Deploy Setup Wizard" -ForegroundColor Cyan Write-Host ("=" * 70) -ForegroundColor Cyan Write-Host "" Write-Host " This wizard will configure automatic deployment monitoring." -ForegroundColor Yellow Write-Host "" Write-Host " What it does:" -ForegroundColor White Write-Host " • Creates directory structure for auto-deployment" -ForegroundColor Gray Write-Host " • Copies Check-And-Deploy.ps1 to scripts folder" -ForegroundColor Gray Write-Host " • Creates Windows Scheduled Task for monitoring" -ForegroundColor Gray Write-Host " • Configures auto-deploy settings" -ForegroundColor Gray Write-Host "" Write-Host ("=" * 70) -ForegroundColor Cyan Write-Host "" Write-Host "Press any key to continue or Ctrl+C to cancel..." -ForegroundColor Yellow $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") } function Get-WizardInput { param( [string]$Prompt, [string]$Default, [switch]$IsNumber, [switch]$IsYesNo ) do { Write-Host "`n$Prompt" -ForegroundColor Yellow if ($Default) { Write-Host " Default: $Default" -ForegroundColor Gray } Write-Host " > " -NoNewline -ForegroundColor Cyan $input = Read-Host # Use default if empty if ([string]::IsNullOrWhiteSpace($input) -and $Default) { return $Default } # Validate number if ($IsNumber) { $num = 0 if ([int]::TryParse($input, [ref]$num) -and $num -gt 0) { return $num } else { Write-Host " Invalid number. Please enter a positive integer." -ForegroundColor Red continue } } # Validate Yes/No if ($IsYesNo) { $normalized = $input.ToUpper() if ($normalized -eq "Y" -or $normalized -eq "YES") { return $true } elseif ($normalized -eq "N" -or $normalized -eq "NO") { return $false } else { Write-Host " Invalid input. Please enter Y or N." -ForegroundColor Red continue } } return $input } while ($true) } # ============================================================================= # SETUP FUNCTIONS # ============================================================================= function Test-Prerequisites { Write-Step "Checking prerequisites..." # Check Administrator $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object Security.Principal.WindowsPrincipal($currentUser) $isAdmin = $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if (-not $isAdmin) { throw "This script requires Administrator privileges" } Write-Success "Running as Administrator" # Check PowerShell version if ($PSVersionTable.PSVersion.Major -lt 5) { throw "PowerShell 5.1 or higher is required" } Write-Success "PowerShell version: $($PSVersionTable.PSVersion)" # Check if Check-And-Deploy.ps1 exists $checkDeployScript = Join-Path $PSScriptRoot "Check-And-Deploy.ps1" if (-not (Test-Path $checkDeployScript)) { throw "Check-And-Deploy.ps1 not found in: $PSScriptRoot" } Write-Success "Check-And-Deploy.ps1 found" return $true } function New-DirectoryStructure { param( [string]$MonitorPath, [string]$ScriptsPath ) Write-Step "Creating directory structure..." # Create monitor path if (-not (Test-Path $MonitorPath)) { New-Item -ItemType Directory -Path $MonitorPath -Force | Out-Null Write-Success "Created: $MonitorPath" } else { Write-Success "Already exists: $MonitorPath" } # Create scripts path if (-not (Test-Path $ScriptsPath)) { New-Item -ItemType Directory -Path $ScriptsPath -Force | Out-Null Write-Success "Created: $ScriptsPath" } else { Write-Success "Already exists: $ScriptsPath" } # Create logs directory $logsPath = Join-Path $ScriptsPath "Logs" if (-not (Test-Path $logsPath)) { New-Item -ItemType Directory -Path $logsPath -Force | Out-Null Write-Success "Created: $logsPath" } else { Write-Success "Already exists: $logsPath" } return $true } function Copy-MonitorScript { param( [string]$SourcePath, [string]$DestPath ) Write-Step "Copying Check-And-Deploy.ps1 to scripts folder..." $sourceScript = Join-Path $SourcePath "Check-And-Deploy.ps1" $destScript = Join-Path $DestPath "Check-And-Deploy.ps1" # Check if source and destination are the same file $sourceFull = (Resolve-Path $sourceScript -ErrorAction SilentlyContinue).Path $destFull = (Resolve-Path $destScript -ErrorAction SilentlyContinue).Path if ($sourceFull -and $destFull -and ($sourceFull -eq $destFull)) { Write-Success "Script already in target location: $destScript" return $destScript } try { Copy-Item -Path $sourceScript -Destination $destScript -Force Write-Success "Script copied to: $destScript" return $destScript } catch { Write-Error "Failed to copy script: $_" return $null } } function New-ScheduledTaskForAutoDeployNew { param( [string]$ScriptPath, [int]$IntervalMinutes, [string]$MonitorPath ) Write-Step "Creating Windows Scheduled Task..." $taskName = "ROA2WEB-AutoDeploy" # Remove existing task if present $existingTask = Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue if ($existingTask) { Write-Info "Removing existing task..." Unregister-ScheduledTask -TaskName $taskName -Confirm:$false } try { # Create action $action = New-ScheduledTaskAction -Execute "PowerShell.exe" ` -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$ScriptPath`" -WatchPath `"$MonitorPath`"" # Create trigger (repeat indefinitely every X minutes) # Note: When RepetitionDuration is not specified, the task repeats indefinitely $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) ` -RepetitionInterval (New-TimeSpan -Minutes $IntervalMinutes) # Create settings $settings = New-ScheduledTaskSettingsSet ` -AllowStartIfOnBatteries ` -DontStopIfGoingOnBatteries ` -StartWhenAvailable ` -RunOnlyIfNetworkAvailable:$false ` -DontStopOnIdleEnd ` -MultipleInstances IgnoreNew # Register task (run as SYSTEM) Register-ScheduledTask -TaskName $taskName ` -Action $action ` -Trigger $trigger ` -Settings $settings ` -User "SYSTEM" ` -RunLevel Highest ` -Description "Monitors $MonitorPath for new deployment packages and auto-deploys them" | Out-Null Write-Success "Scheduled task created: $taskName" Write-Success "Interval: Every $IntervalMinutes minutes" Write-Success "User: SYSTEM" Write-Success "Status: Enabled" return $true } catch { Write-Error "Failed to create scheduled task: $_" return $false } } function Show-SetupSummary { param( [hashtable]$Config ) Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan Write-Host " Setup Summary" -ForegroundColor Cyan Write-Host ("=" * 70) -ForegroundColor Cyan Write-Host "" Write-Host " Monitor Path: $($Config.MonitorPath)" -ForegroundColor Gray Write-Host " Scripts Path: $($Config.ScriptsPath)" -ForegroundColor Gray Write-Host " Check Interval: $($Config.CheckIntervalMinutes) minutes" -ForegroundColor Gray Write-Host " Auto-Deploy: $($Config.AutoDeploy)" -ForegroundColor Gray Write-Host " Scheduled Task: $($Config.CreateScheduledTask)" -ForegroundColor Gray Write-Host "" Write-Host ("=" * 70) -ForegroundColor Cyan Write-Host "" Write-Host "Proceed with setup? [Y/N]: " -ForegroundColor Yellow -NoNewline $confirm = Read-Host return ($confirm.ToUpper() -eq "Y" -or $confirm.ToUpper() -eq "YES") } # ============================================================================= # MAIN SETUP FLOW # ============================================================================= function Invoke-Setup { param([hashtable]$Config) Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan Write-Host " Starting Setup" -ForegroundColor Cyan Write-Host ("=" * 70) -ForegroundColor Cyan try { # Test prerequisites Test-Prerequisites | Out-Null # Create directory structure New-DirectoryStructure -MonitorPath $Config.MonitorPath -ScriptsPath $Config.ScriptsPath | Out-Null # Copy monitor script $scriptPath = Copy-MonitorScript -SourcePath $PSScriptRoot -DestPath $Config.ScriptsPath if (-not $scriptPath) { throw "Failed to copy monitor script" } # Create scheduled task if requested if ($Config.CreateScheduledTask) { $taskSuccess = New-ScheduledTaskForAutoDeployNew ` -ScriptPath $scriptPath ` -IntervalMinutes $Config.CheckIntervalMinutes ` -MonitorPath $Config.MonitorPath if (-not $taskSuccess) { throw "Failed to create scheduled task" } } Write-Host "`n" + ("=" * 70) -ForegroundColor Green Write-Host " SETUP COMPLETED SUCCESSFULLY" -ForegroundColor Green Write-Host ("=" * 70) -ForegroundColor Green Write-Host "" Write-Host " Next Steps:" -ForegroundColor Yellow Write-Host " 1. Deploy packages will be placed in: $($Config.MonitorPath)" -ForegroundColor Gray Write-Host " 2. Server will check for updates every $($Config.CheckIntervalMinutes) minutes" -ForegroundColor Gray Write-Host " 3. New packages will be deployed automatically" -ForegroundColor Gray Write-Host "" Write-Host " Manual Testing:" -ForegroundColor Yellow Write-Host " - Test: cd $($Config.ScriptsPath) && .\\Check-And-Deploy.ps1 -Interactive" -ForegroundColor Gray Write-Host " - View Task: Get-ScheduledTask -TaskName 'ROA2WEB-AutoDeploy'" -ForegroundColor Gray Write-Host "" Write-Host ("=" * 70) -ForegroundColor Green return $true } catch { Write-Host "`n" + ("=" * 70) -ForegroundColor Red Write-Host " SETUP FAILED" -ForegroundColor Red Write-Host ("=" * 70) -ForegroundColor Red Write-Host "" Write-Error $_ Write-Host "" Write-Host ("=" * 70) -ForegroundColor Red return $false } } # ============================================================================= # MAIN EXECUTION FLOW # ============================================================================= function Main { # Non-interactive mode if ($NonInteractive) { $config = @{ MonitorPath = $MonitorPath ScriptsPath = $ScriptsPath CheckIntervalMinutes = $CheckIntervalMinutes AutoDeploy = $AutoDeploy CreateScheduledTask = $CreateScheduledTask } Invoke-Setup -Config $config | Out-Null return } # Interactive mode - Wizard Show-WizardWelcome Write-Host "`n" + ("=" * 70) -ForegroundColor Cyan Write-Host " Configuration Wizard" -ForegroundColor Cyan Write-Host ("=" * 70) -ForegroundColor Cyan # Step 1: Monitor Path $monitorPath = Get-WizardInput -Prompt "[1/5] Deploy Folder Path`n Path to monitor for new deployment packages:" -Default $MonitorPath # Step 2: Scripts Path $scriptsPath = Get-WizardInput -Prompt "[2/5] Scripts Folder Path`n Path to store monitoring scripts:" -Default $ScriptsPath # Step 3: Check Interval $checkInterval = Get-WizardInput -Prompt "[3/5] Check Interval`n How often to check for updates (minutes):" -Default $CheckIntervalMinutes -IsNumber # Step 4: Auto-Deploy Write-Host "`n[4/5] Auto-Deploy Enabled" -ForegroundColor Yellow Write-Host " Deploy automatically when new package found?" -ForegroundColor Yellow Write-Host " [Y] Yes (recommended) [N] No (manual trigger only)" -ForegroundColor Gray $autoDeploy = Get-WizardInput -Prompt " Your choice:" -Default "Y" -IsYesNo # Step 5: Scheduled Task Write-Host "`n[5/5] Create Scheduled Task" -ForegroundColor Yellow Write-Host " Create Windows Scheduled Task for automatic monitoring?" -ForegroundColor Yellow Write-Host " [Y] Yes [N] No" -ForegroundColor Gray $createTask = Get-WizardInput -Prompt " Your choice:" -Default "Y" -IsYesNo # Configuration object $config = @{ MonitorPath = $monitorPath ScriptsPath = $scriptsPath CheckIntervalMinutes = [int]$checkInterval AutoDeploy = $autoDeploy CreateScheduledTask = $createTask } # Show summary and confirm $confirmed = Show-SetupSummary -Config $config if ($confirmed) { Invoke-Setup -Config $config } else { Write-Host "`nSetup cancelled by user" -ForegroundColor Yellow exit 0 } Write-Host "`nPress any key to exit..." -ForegroundColor Gray $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") } # Run main Main