xetup/Deploy-Windows.ps1

245 lines
9.2 KiB
PowerShell
Raw Permalink Normal View History

#Requires -RunAsAdministrator
[CmdletBinding()]
param(
[switch]$SkipBloatware,
[switch]$SkipSoftware,
[switch]$SkipDefaultProfile,
[switch]$DryRun
)
$ErrorActionPreference = "Continue"
# -----------------------------------------------------------------------
# Paths
# -----------------------------------------------------------------------
$ScriptRoot = $PSScriptRoot
$LogDir = "C:\Windows\Setup\Scripts"
$LogFile = "$LogDir\Deploy.log"
$ConfigFile = "$ScriptRoot\config\config.json"
# -----------------------------------------------------------------------
# Logging
# -----------------------------------------------------------------------
function Write-Log {
param(
[string]$Message,
[ValidateSet("INFO","OK","ERROR","WARN","STEP")]
[string]$Level = "INFO"
)
$timestamp = Get-Date -Format "HH:mm:ss"
$line = "[$timestamp] [$Level] $Message"
Add-Content -Path $LogFile -Value $line -Encoding UTF8
switch ($Level) {
"OK" { Write-Host $line -ForegroundColor Green }
"ERROR" { Write-Host $line -ForegroundColor Red }
"WARN" { Write-Host $line -ForegroundColor Yellow }
"STEP" { Write-Host $line -ForegroundColor Cyan }
default { Write-Host $line }
}
}
# -----------------------------------------------------------------------
# Step runner - catches errors, logs, always continues
# -----------------------------------------------------------------------
$StepResults = [System.Collections.Generic.List[hashtable]]::new()
function Invoke-Step {
param(
[string]$Name,
[scriptblock]$Action
)
Write-Log "---- $Name ----" -Level STEP
if ($DryRun) {
Write-Log "DryRun - skipping execution" -Level WARN
$StepResults.Add(@{ Name = $Name; Status = "DRYRUN" })
return
}
try {
& $Action
Write-Log "$Name - OK" -Level OK
$StepResults.Add(@{ Name = $Name; Status = "OK" })
}
catch {
Write-Log "$Name - ERROR: $_" -Level ERROR
$StepResults.Add(@{ Name = $Name; Status = "ERROR" })
}
}
# -----------------------------------------------------------------------
# Init
# -----------------------------------------------------------------------
if (-not (Test-Path $LogDir)) {
New-Item -ItemType Directory -Path $LogDir -Force | Out-Null
}
Write-Log "========================================" -Level INFO
Write-Log "Deploy-Windows.ps1 started" -Level INFO
Write-Log "Computer: $env:COMPUTERNAME" -Level INFO
Write-Log "User: $env:USERNAME" -Level INFO
Write-Log "Date: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -Level INFO
if ($DryRun) { Write-Log "Mode: DRY RUN" -Level WARN }
Write-Log "========================================" -Level INFO
# -----------------------------------------------------------------------
# Load config
# -----------------------------------------------------------------------
$Config = $null
Invoke-Step -Name "Load config.json" -Action {
if (-not (Test-Path $ConfigFile)) {
throw "config.json not found: $ConfigFile"
}
$script:Config = Get-Content $ConfigFile -Raw -Encoding UTF8 | ConvertFrom-Json
Write-Log "Config loaded from $ConfigFile" -Level INFO
}
# -----------------------------------------------------------------------
# Build step enable/disable map from config + CLI overrides
# -----------------------------------------------------------------------
$stepsEnabled = @{
adminAccount = $true
bloatware = $true
software = $true
systemRegistry = $true
defaultProfile = $true
personalization = $true
scheduledTasks = $true
desktopInfo = $true
activation = $true
}
if ($Config -and $Config.steps) {
foreach ($key in @($stepsEnabled.Keys)) {
$val = $Config.steps.$key
if ($null -ne $val) { $stepsEnabled[$key] = [bool]$val }
}
}
# CLI switches override config.steps
if ($SkipBloatware) { $stepsEnabled['bloatware'] = $false }
if ($SkipSoftware) { $stepsEnabled['software'] = $false }
if ($SkipDefaultProfile) { $stepsEnabled['defaultProfile'] = $false }
function Skip-Step {
param([string]$Name)
Write-Log "$Name - SKIPPED (disabled in config)" -Level WARN
$StepResults.Add(@{ Name = $Name; Status = "SKIPPED" })
}
# -----------------------------------------------------------------------
# Step 0a - Admin account
# -----------------------------------------------------------------------
if ($stepsEnabled['adminAccount']) {
Invoke-Step -Name "Step 0a - Admin account" -Action {
& "$ScriptRoot\scripts\00-admin-account.ps1" -Config $Config -LogFile $LogFile
}
} else { Skip-Step "Step 0a - Admin account" }
# -----------------------------------------------------------------------
# Step 0b - Windows activation
# -----------------------------------------------------------------------
if ($stepsEnabled['activation']) {
Invoke-Step -Name "Step 0b - Windows activation" -Action {
& "$ScriptRoot\scripts\08-activation.ps1" -Config $Config -LogFile $LogFile
}
} else { Skip-Step "Step 0b - Windows activation" }
# -----------------------------------------------------------------------
# Step 1 - Bloatware removal
# -----------------------------------------------------------------------
if ($stepsEnabled['bloatware']) {
Invoke-Step -Name "Step 1 - Bloatware removal" -Action {
& "$ScriptRoot\scripts\01-bloatware.ps1" -Config $Config -LogFile $LogFile
}
} else { Skip-Step "Step 1 - Bloatware removal" }
# -----------------------------------------------------------------------
# Step 2 - Software installation
# -----------------------------------------------------------------------
if ($stepsEnabled['software']) {
Invoke-Step -Name "Step 2 - Software installation" -Action {
& "$ScriptRoot\scripts\02-software.ps1" -Config $Config -LogFile $LogFile
}
} else { Skip-Step "Step 2 - Software installation" }
# -----------------------------------------------------------------------
# Step 3 - System registry (HKLM)
# -----------------------------------------------------------------------
if ($stepsEnabled['systemRegistry']) {
Invoke-Step -Name "Step 3 - System registry" -Action {
& "$ScriptRoot\scripts\03-system-registry.ps1" -Config $Config -LogFile $LogFile
}
} else { Skip-Step "Step 3 - System registry" }
# -----------------------------------------------------------------------
# Step 4 - Default profile (NTUSER.DAT)
# -----------------------------------------------------------------------
if ($stepsEnabled['defaultProfile']) {
Invoke-Step -Name "Step 4 - Default profile" -Action {
& "$ScriptRoot\scripts\04-default-profile.ps1" -Config $Config -LogFile $LogFile
}
} else { Skip-Step "Step 4 - Default profile" }
# -----------------------------------------------------------------------
# Step 5 - Personalization
# -----------------------------------------------------------------------
if ($stepsEnabled['personalization']) {
Invoke-Step -Name "Step 5 - Personalization" -Action {
& "$ScriptRoot\scripts\05-personalization.ps1" -Config $Config -LogFile $LogFile
}
} else { Skip-Step "Step 5 - Personalization" }
# -----------------------------------------------------------------------
# Step 6 - Scheduled tasks
# -----------------------------------------------------------------------
if ($stepsEnabled['scheduledTasks']) {
Invoke-Step -Name "Step 6 - Scheduled tasks" -Action {
& "$ScriptRoot\scripts\06-scheduled-tasks.ps1" -Config $Config -LogFile $LogFile
}
} else { Skip-Step "Step 6 - Scheduled tasks" }
# -----------------------------------------------------------------------
# Step 7 - DesktopInfo
# -----------------------------------------------------------------------
if ($stepsEnabled['desktopInfo']) {
Invoke-Step -Name "Step 7 - DesktopInfo" -Action {
& "$ScriptRoot\scripts\07-desktop-info.ps1" -Config $Config -LogFile $LogFile
}
} else { Skip-Step "Step 7 - DesktopInfo" }
# -----------------------------------------------------------------------
# Summary
# -----------------------------------------------------------------------
Write-Log "========================================" -Level INFO
Write-Log "SUMMARY" -Level INFO
Write-Log "========================================" -Level INFO
$countOK = ($StepResults | Where-Object { $_.Status -eq "OK" }).Count
$countError = ($StepResults | Where-Object { $_.Status -eq "ERROR" }).Count
$countSkipped = ($StepResults | Where-Object { $_.Status -eq "SKIPPED" }).Count
$countDryRun = ($StepResults | Where-Object { $_.Status -eq "DRYRUN" }).Count
foreach ($r in $StepResults) {
$lvl = switch ($r.Status) {
"OK" { "OK" }
"ERROR" { "ERROR" }
"SKIPPED" { "WARN" }
"DRYRUN" { "WARN" }
}
Write-Log "$($r.Status.PadRight(8)) $($r.Name)" -Level $lvl
}
Write-Log "----------------------------------------" -Level INFO
Write-Log "OK: $countOK ERROR: $countError SKIPPED: $countSkipped DRYRUN: $countDryRun" -Level INFO
Write-Log "Log saved to: $LogFile" -Level INFO
Write-Log "========================================" -Level INFO
if ($countError -gt 0) {
Write-Log "Deployment finished with errors. Review log: $LogFile" -Level ERROR
exit 1
} else {
Write-Log "Deployment finished successfully." -Level OK
exit 0
}