build-pe-script-launcher/resources/Invoke-ScriptMenu.ps1
Claude b06374a562 Initial commit: Build PE Script Launcher
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>
2026-01-12 16:39:43 -05:00

252 lines
6.5 KiB
PowerShell

#Requires -Version 5.1
<#
.SYNOPSIS
Built-in Script Menu for WinPE Script Launcher
.DESCRIPTION
Discovers and executes scripts from a .scripts folder. This is a simplified
version designed for WinPE environments without UAC elevation requirements.
#>
[CmdletBinding()]
param(
[string]$ScriptsPath = ".scripts"
)
$Script:SupportedExtensions = @('.ps1', '.bat', '.cmd')
$Script:ExitCode = 0
function Write-Header {
param([string]$Title)
$width = 70
Write-Host ""
Write-Host ("=" * $width) -ForegroundColor Cyan
Write-Host " $Title" -ForegroundColor Yellow
Write-Host ("=" * $width) -ForegroundColor Cyan
Write-Host ""
}
function Write-InfoBox {
param(
[string]$Message,
[string]$Type = 'Info'
)
$color = switch ($Type) {
'Success' { 'Green' }
'Warning' { 'Yellow' }
'Error' { 'Red' }
default { 'Cyan' }
}
$icon = switch ($Type) {
'Success' { '[+]' }
'Warning' { '[!]' }
'Error' { '[X]' }
default { '[i]' }
}
Write-Host "$icon " -ForegroundColor $color -NoNewline
Write-Host $Message
}
function Write-Separator {
Write-Host ("-" * 70) -ForegroundColor DarkGray
}
function Get-ScriptFiles {
param([string]$Path)
if (-not (Test-Path $Path)) {
return $null
}
$scripts = Get-ChildItem -Path $Path -File -ErrorAction SilentlyContinue |
Where-Object { $Script:SupportedExtensions -contains $_.Extension } |
Sort-Object Name
return $scripts
}
function Show-ScriptMenu {
param([array]$Scripts)
Write-Host " Available Scripts:" -ForegroundColor Green
Write-Host ""
for ($i = 0; $i -lt $Scripts.Count; $i++) {
$num = $i + 1
$script = $Scripts[$i]
$ext = $script.Extension
$extColor = switch ($ext) {
'.ps1' { 'Magenta' }
'.bat' { 'Yellow' }
'.cmd' { 'Cyan' }
default { 'White' }
}
Write-Host " " -NoNewline
Write-Host ("[{0,2}]" -f $num) -ForegroundColor White -NoNewline
Write-Host " " -NoNewline
Write-Host $script.Name -ForegroundColor $extColor
}
Write-Host ""
Write-Separator
Write-Host ""
}
function Get-UserSelection {
param([int]$MaxNumber)
Write-Host " Selection Options:" -ForegroundColor Yellow
Write-Host " - Enter number (e.g., '1')" -ForegroundColor Gray
Write-Host " - Enter 'all' to run all scripts sequentially" -ForegroundColor Gray
Write-Host " - Enter 'q' or 'quit' to exit" -ForegroundColor Gray
Write-Host ""
while ($true) {
Write-Host " Select script to run: " -ForegroundColor Cyan -NoNewline
$input = Read-Host
if ([string]::IsNullOrWhiteSpace($input)) {
Write-InfoBox "Please enter a selection" "Warning"
continue
}
$input = $input.Trim().ToLower()
if ($input -eq 'q' -or $input -eq 'quit') {
return $null
}
if ($input -eq 'all') {
return 1..$MaxNumber
}
if ($input -match '^\d+$') {
$num = [int]$input
if ($num -lt 1 -or $num -gt $MaxNumber) {
Write-InfoBox "Invalid number. Please enter 1-$MaxNumber" "Error"
continue
}
return @($num)
}
Write-InfoBox "Invalid input. Please try again" "Error"
}
}
function Invoke-Script {
param(
[string]$ScriptPath,
[string]$ScriptName
)
Write-Host ""
Write-InfoBox "Executing: $ScriptName" "Info"
Write-Host ""
$extension = [System.IO.Path]::GetExtension($ScriptPath)
try {
if ($extension -eq '.ps1') {
& $ScriptPath
$exitCode = $LASTEXITCODE
}
else {
$process = Start-Process -FilePath $ScriptPath -Wait -PassThru -NoNewWindow
$exitCode = $process.ExitCode
}
Write-Host ""
if ($exitCode -eq 0 -or $null -eq $exitCode) {
Write-InfoBox "Completed: $ScriptName" "Success"
}
else {
Write-InfoBox "Completed with exit code $exitCode: $ScriptName" "Warning"
$Script:ExitCode = $exitCode
}
}
catch {
Write-InfoBox "Failed to execute: $ScriptName" "Error"
Write-InfoBox "Error: $($_.Exception.Message)" "Error"
$Script:ExitCode = 1
}
}
function Start-ScriptMenu {
try {
Clear-Host
Write-Header "WinPE SCRIPT MENU"
if (-not (Test-Path $ScriptsPath)) {
Write-InfoBox "Scripts folder not found: $ScriptsPath" "Error"
Write-Host ""
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
exit 1
}
Write-InfoBox "Scripts Folder: $ScriptsPath" "Info"
$scripts = Get-ScriptFiles -Path $ScriptsPath
if ($null -eq $scripts -or $scripts.Count -eq 0) {
Write-Host ""
Write-InfoBox "No scripts found" "Warning"
Write-InfoBox "Supported: $($Script:SupportedExtensions -join ', ')" "Info"
Write-Host ""
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
exit 1
}
Write-InfoBox "Found $($scripts.Count) script(s)" "Success"
Write-Host ""
Write-Separator
Write-Host ""
Show-ScriptMenu -Scripts $scripts
$selections = Get-UserSelection -MaxNumber $scripts.Count
if ($null -eq $selections) {
Write-Host ""
Write-InfoBox "Exiting..." "Info"
Write-Host ""
exit 0
}
Write-Host ""
Write-Header "Executing Selected Scripts"
foreach ($selection in $selections) {
$script = $scripts[$selection - 1]
Invoke-Script -ScriptPath $script.FullName -ScriptName $script.Name
}
Write-Host ""
Write-Separator
Write-InfoBox "All scripts completed" "Success"
Write-Host ""
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
exit $Script:ExitCode
}
catch {
Write-Host ""
Write-InfoBox "FATAL ERROR: $($_.Exception.Message)" "Error"
Write-Host ""
Write-Host "Press any key to exit..." -ForegroundColor Gray
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
exit 1
}
}
Start-ScriptMenu