Production-grade Windows PE builder with PowerShell 7 integration. Features: - PowerShell 7 integrated into WinPE environment - Automatic script launcher for external media - Configurable startup and fallback scripts - Custom console colors - Maximized console window on boot - PowerShell module integration - Windows ADK auto-installation - Defender optimization for faster builds Project Structure: - Build-PE.ps1: Main build orchestrator - config.json: Configuration file - lib/: Build modules (Dependencies, WinPEBuilder, PowerShell7, ModuleManager, DefenderOptimization) - resources/: Runtime scripts (Invoke-ScriptLauncher, Invoke-ScriptMenu, Driver-Manager) - CLAUDE.md: Complete project documentation - README.md: Quick start guide Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
196 lines
6.6 KiB
PowerShell
196 lines
6.6 KiB
PowerShell
function Test-AdminPrivileges {
|
|
<#
|
|
.SYNOPSIS
|
|
Verifies script is running with administrator privileges.
|
|
#>
|
|
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
|
|
return $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
|
}
|
|
|
|
function Test-WindowsADK {
|
|
<#
|
|
.SYNOPSIS
|
|
Checks if Windows ADK and WinPE add-on are installed.
|
|
#>
|
|
try {
|
|
$adkPath = "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit"
|
|
$deploymentToolsPath = Join-Path $adkPath "Deployment Tools"
|
|
$winPEPath = Join-Path $adkPath "Windows Preinstallation Environment"
|
|
|
|
$registryPath = "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots"
|
|
$registryExists = Test-Path $registryPath
|
|
|
|
if (-not $registryExists) {
|
|
Write-Verbose "ADK registry key not found"
|
|
return $false
|
|
}
|
|
|
|
if (-not (Test-Path $deploymentToolsPath)) {
|
|
Write-Verbose "Deployment Tools not found at: $deploymentToolsPath"
|
|
return $false
|
|
}
|
|
|
|
if (-not (Test-Path $winPEPath)) {
|
|
Write-Verbose "WinPE add-on not found at: $winPEPath"
|
|
return $false
|
|
}
|
|
|
|
$dismPath = Join-Path $deploymentToolsPath "DISM\dism.exe"
|
|
$copypePath = Join-Path $winPEPath "copype.cmd"
|
|
|
|
if (-not (Test-Path $dismPath)) {
|
|
Write-Verbose "DISM executable not found"
|
|
return $false
|
|
}
|
|
|
|
if (-not (Test-Path $copypePath)) {
|
|
Write-Verbose "copype.cmd not found"
|
|
return $false
|
|
}
|
|
|
|
Write-Verbose "Windows ADK and WinPE add-on are installed"
|
|
return $true
|
|
}
|
|
catch {
|
|
Write-Verbose "Error checking ADK: $_"
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Install-WindowsADK {
|
|
<#
|
|
.SYNOPSIS
|
|
Downloads and installs Windows ADK and WinPE add-on silently.
|
|
#>
|
|
[CmdletBinding()]
|
|
param()
|
|
|
|
Write-Host "`n=== Windows ADK Installation ===" -ForegroundColor Cyan
|
|
Write-Host "This will download and install:"
|
|
Write-Host " - Windows ADK (~150MB download)"
|
|
Write-Host " - WinPE Add-on (~5GB download)"
|
|
Write-Host " - Total time: ~20-30 minutes depending on connection`n"
|
|
|
|
$downloadsDir = ".\downloads"
|
|
if (-not (Test-Path $downloadsDir)) {
|
|
New-Item -ItemType Directory -Path $downloadsDir | Out-Null
|
|
}
|
|
|
|
$adkInstallerPath = Join-Path $downloadsDir "adksetup.exe"
|
|
$winpeInstallerPath = Join-Path $downloadsDir "adkwinpesetup.exe"
|
|
|
|
$adkUrl = "https://go.microsoft.com/fwlink/?linkid=2271337"
|
|
$winpeUrl = "https://go.microsoft.com/fwlink/?linkid=2271338"
|
|
|
|
try {
|
|
Write-Host "[1/4] Downloading Windows ADK installer..." -ForegroundColor Yellow
|
|
if (-not (Test-Path $adkInstallerPath)) {
|
|
$ProgressPreference = 'SilentlyContinue'
|
|
Invoke-WebRequest -Uri $adkUrl -OutFile $adkInstallerPath -UseBasicParsing
|
|
$ProgressPreference = 'Continue'
|
|
Write-Host " ✓ ADK installer downloaded" -ForegroundColor Green
|
|
} else {
|
|
Write-Host " ✓ ADK installer already exists" -ForegroundColor Green
|
|
}
|
|
|
|
Write-Host "[2/4] Installing Windows ADK (this may take 5-10 minutes)..." -ForegroundColor Yellow
|
|
$adkProcess = Start-Process -FilePath $adkInstallerPath `
|
|
-ArgumentList "/quiet", "/norestart", "/features", "OptionId.DeploymentTools" `
|
|
-Wait -PassThru -NoNewWindow
|
|
|
|
if ($adkProcess.ExitCode -ne 0) {
|
|
throw "ADK installation failed with exit code: $($adkProcess.ExitCode)"
|
|
}
|
|
Write-Host " ✓ Windows ADK installed successfully" -ForegroundColor Green
|
|
|
|
Write-Host "[3/4] Downloading WinPE add-on installer (large download)..." -ForegroundColor Yellow
|
|
if (-not (Test-Path $winpeInstallerPath)) {
|
|
$ProgressPreference = 'SilentlyContinue'
|
|
Invoke-WebRequest -Uri $winpeUrl -OutFile $winpeInstallerPath -UseBasicParsing
|
|
$ProgressPreference = 'Continue'
|
|
Write-Host " ✓ WinPE installer downloaded" -ForegroundColor Green
|
|
} else {
|
|
Write-Host " ✓ WinPE installer already exists" -ForegroundColor Green
|
|
}
|
|
|
|
Write-Host "[4/4] Installing WinPE add-on (this may take 10-15 minutes)..." -ForegroundColor Yellow
|
|
$winpeProcess = Start-Process -FilePath $winpeInstallerPath `
|
|
-ArgumentList "/quiet", "/norestart", "/features", "OptionId.WindowsPreinstallationEnvironment" `
|
|
-Wait -PassThru -NoNewWindow
|
|
|
|
if ($winpeProcess.ExitCode -ne 0) {
|
|
throw "WinPE add-on installation failed with exit code: $($winpeProcess.ExitCode)"
|
|
}
|
|
Write-Host " ✓ WinPE add-on installed successfully" -ForegroundColor Green
|
|
|
|
Write-Host "`n✓ Windows ADK and WinPE add-on installation complete!`n" -ForegroundColor Green
|
|
}
|
|
catch {
|
|
Write-Error "Failed to install Windows ADK: $_"
|
|
throw
|
|
}
|
|
}
|
|
|
|
function Test-PowerShell7Archive {
|
|
<#
|
|
.SYNOPSIS
|
|
Verifies PowerShell 7 zip archive exists locally.
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[PSCustomObject]$Config
|
|
)
|
|
|
|
$ps7FileName = "PowerShell-$($Config.powershell7Version)-win-x64.zip"
|
|
$ps7Path = Join-Path (Get-Location) $ps7FileName
|
|
|
|
if (Test-Path $ps7Path) {
|
|
Write-Verbose "PowerShell 7 archive found: $ps7Path"
|
|
return $true
|
|
}
|
|
|
|
Write-Verbose "PowerShell 7 archive not found: $ps7Path"
|
|
return $false
|
|
}
|
|
|
|
function Get-PowerShell7Archive {
|
|
<#
|
|
.SYNOPSIS
|
|
Downloads PowerShell 7 zip archive from GitHub.
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[PSCustomObject]$Config
|
|
)
|
|
|
|
$ps7FileName = "PowerShell-$($Config.powershell7Version)-win-x64.zip"
|
|
$ps7Path = Join-Path (Get-Location) $ps7FileName
|
|
|
|
Write-Host "Downloading PowerShell $($Config.powershell7Version)..." -ForegroundColor Yellow
|
|
|
|
try {
|
|
$ProgressPreference = 'SilentlyContinue'
|
|
Invoke-WebRequest -Uri $Config.powershell7ZipUrl -OutFile $ps7Path -UseBasicParsing
|
|
$ProgressPreference = 'Continue'
|
|
|
|
if (Test-Path $ps7Path) {
|
|
Write-Host " ✓ PowerShell 7 downloaded successfully" -ForegroundColor Green
|
|
} else {
|
|
throw "Download completed but file not found"
|
|
}
|
|
}
|
|
catch {
|
|
Write-Error "Failed to download PowerShell 7: $_"
|
|
throw
|
|
}
|
|
}
|
|
|
|
Export-ModuleMember -Function @(
|
|
'Test-AdminPrivileges',
|
|
'Test-WindowsADK',
|
|
'Install-WindowsADK',
|
|
'Test-PowerShell7Archive',
|
|
'Get-PowerShell7Archive'
|
|
)
|