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>
239 lines
7.8 KiB
PowerShell
239 lines
7.8 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
WinPE Script Launcher - Automatically detects and runs scripts from external media.
|
|
|
|
.DESCRIPTION
|
|
This script runs automatically when WinPE boots. It scans all available drives
|
|
for a .scripts folder on the root, then executes the configured target script.
|
|
#>
|
|
|
|
$ErrorActionPreference = "Continue"
|
|
|
|
# Load configuration from WinPE image
|
|
$ConfigPath = "X:\Windows\System32\winpe-config.json"
|
|
$Config = $null
|
|
|
|
if (Test-Path $ConfigPath) {
|
|
try {
|
|
$Config = Get-Content $ConfigPath -Raw | ConvertFrom-Json
|
|
$ScriptsFolder = $Config.scriptsFolder
|
|
$TargetScript = $Config.targetScript
|
|
$FallbackScript = $Config.fallbackScript
|
|
}
|
|
catch {
|
|
Write-Warning "Failed to load config, using defaults"
|
|
$ScriptsFolder = ".scripts"
|
|
$TargetScript = "Invoke-ScriptMenu.ps1"
|
|
$FallbackScript = "Invoke-ScriptMenu.ps1"
|
|
}
|
|
}
|
|
else {
|
|
# Fallback to defaults if config not found
|
|
$ScriptsFolder = ".scripts"
|
|
$TargetScript = "Invoke-ScriptMenu.ps1"
|
|
$FallbackScript = "Invoke-ScriptMenu.ps1"
|
|
}
|
|
|
|
# Apply console customizations
|
|
try {
|
|
$host.UI.RawUI.WindowTitle = 'WinPE Script Launcher - PowerShell 7'
|
|
|
|
# Set console colors if configured
|
|
if ($Config -and $Config.consoleColors) {
|
|
if ($Config.consoleColors.backgroundColor) {
|
|
$host.UI.RawUI.BackgroundColor = $Config.consoleColors.backgroundColor
|
|
}
|
|
if ($Config.consoleColors.foregroundColor) {
|
|
$host.UI.RawUI.ForegroundColor = $Config.consoleColors.foregroundColor
|
|
}
|
|
Clear-Host # Apply color changes
|
|
}
|
|
|
|
# Get console window handle and maximize it
|
|
Add-Type -MemberDefinition @'
|
|
[DllImport("kernel32.dll")]
|
|
public static extern IntPtr GetConsoleWindow();
|
|
'@ -Name Console -Namespace Win32 -PassThru -ErrorAction SilentlyContinue | Out-Null
|
|
|
|
Add-Type -TypeDefinition @'
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
public class User32 {
|
|
[DllImport("user32.dll")]
|
|
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
|
}
|
|
'@ -ErrorAction SilentlyContinue
|
|
|
|
$consoleWindow = [Win32.Console]::GetConsoleWindow()
|
|
$SW_MAXIMIZE = 3
|
|
[User32]::ShowWindow($consoleWindow, $SW_MAXIMIZE) | Out-Null
|
|
}
|
|
catch {
|
|
# Silently continue if window manipulation fails
|
|
}
|
|
|
|
function Write-Banner {
|
|
Write-Host ""
|
|
Write-Host "=============================================" -ForegroundColor Cyan
|
|
Write-Host " WinPE Script Launcher v1.0" -ForegroundColor White
|
|
Write-Host "=============================================" -ForegroundColor Cyan
|
|
Write-Host ""
|
|
}
|
|
|
|
function Find-ScriptsFolder {
|
|
param(
|
|
[string]$FolderName
|
|
)
|
|
|
|
Write-Host "Scanning drives for [$FolderName] folder..." -ForegroundColor Yellow
|
|
Write-Host ""
|
|
|
|
Start-Sleep -Seconds 2
|
|
|
|
try {
|
|
$drives = Get-PSDrive -PSProvider FileSystem -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.Used -gt 0 -and $_.Root -ne "X:\" }
|
|
|
|
if (-not $drives) {
|
|
Write-Warning "No drives found with content"
|
|
return $null
|
|
}
|
|
|
|
foreach ($drive in $drives) {
|
|
$testPath = Join-Path $drive.Root $FolderName
|
|
Write-Host " Checking $($drive.Root)..." -ForegroundColor Cyan
|
|
|
|
if (Test-Path $testPath) {
|
|
Write-Host " [FOUND] $testPath" -ForegroundColor Green
|
|
Write-Host ""
|
|
return $testPath
|
|
}
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Warning "No [$FolderName] folder found on any drive"
|
|
return $null
|
|
}
|
|
catch {
|
|
Write-Error "Error scanning drives: $_"
|
|
return $null
|
|
}
|
|
}
|
|
|
|
function Invoke-TargetScript {
|
|
param(
|
|
[string]$ScriptsPath,
|
|
[string]$ScriptName
|
|
)
|
|
|
|
$scriptPath = Join-Path $ScriptsPath $ScriptName
|
|
|
|
if (-not (Test-Path $scriptPath)) {
|
|
Write-Error "Target script not found: $scriptPath"
|
|
Write-Host ""
|
|
Write-Host "Expected script: $ScriptName" -ForegroundColor Yellow
|
|
Write-Host "Scripts folder: $ScriptsPath" -ForegroundColor Yellow
|
|
Write-Host ""
|
|
Write-Host "Available files in scripts folder:" -ForegroundColor Cyan
|
|
|
|
try {
|
|
Get-ChildItem -Path $ScriptsPath -File | ForEach-Object {
|
|
Write-Host " - $($_.Name)" -ForegroundColor White
|
|
}
|
|
}
|
|
catch {
|
|
Write-Warning "Could not list files in scripts folder"
|
|
}
|
|
|
|
return $false
|
|
}
|
|
|
|
Write-Host "Executing: $scriptPath" -ForegroundColor Green
|
|
Write-Host ""
|
|
Write-Host "-------------------------------------------" -ForegroundColor DarkGray
|
|
Write-Host ""
|
|
|
|
try {
|
|
Push-Location $ScriptsPath
|
|
|
|
& $scriptPath
|
|
|
|
Pop-Location
|
|
|
|
Write-Host ""
|
|
Write-Host "-------------------------------------------" -ForegroundColor DarkGray
|
|
Write-Host "Script execution completed" -ForegroundColor Green
|
|
return $true
|
|
}
|
|
catch {
|
|
Pop-Location
|
|
Write-Error "Script execution failed: $_"
|
|
return $false
|
|
}
|
|
}
|
|
|
|
Write-Banner
|
|
|
|
$scriptsPath = Find-ScriptsFolder -FolderName $ScriptsFolder
|
|
|
|
if ($scriptsPath) {
|
|
Write-Host "Scripts folder located at: $scriptsPath" -ForegroundColor Green
|
|
Write-Host ""
|
|
|
|
$success = Invoke-TargetScript -ScriptsPath $scriptsPath -ScriptName $TargetScript
|
|
|
|
if (-not $success) {
|
|
Write-Host ""
|
|
Write-Host "Press any key to continue to command prompt..." -ForegroundColor Yellow
|
|
$null = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
|
}
|
|
}
|
|
else {
|
|
Write-Host ""
|
|
Write-Host "=============================================" -ForegroundColor Yellow
|
|
Write-Host " No external scripts found" -ForegroundColor Yellow
|
|
Write-Host "=============================================" -ForegroundColor Yellow
|
|
Write-Host ""
|
|
|
|
$localScriptsPath = "X:\$ScriptsFolder"
|
|
if (Test-Path $localScriptsPath) {
|
|
Write-Host "Found local scripts folder on WinPE image" -ForegroundColor Green
|
|
Write-Host "Launching built-in fallback script..." -ForegroundColor Cyan
|
|
Write-Host ""
|
|
Start-Sleep -Seconds 1
|
|
|
|
$fallbackScriptPath = "X:\Windows\System32\$FallbackScript"
|
|
if (Test-Path $fallbackScriptPath) {
|
|
try {
|
|
& $fallbackScriptPath -ScriptsPath $localScriptsPath
|
|
}
|
|
catch {
|
|
Write-Error "Failed to launch fallback script: $_"
|
|
Write-Host ""
|
|
Write-Host "Press any key to continue to command prompt..." -ForegroundColor Yellow
|
|
$null = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
|
}
|
|
}
|
|
else {
|
|
Write-Warning "Fallback script not found in WinPE image: $FallbackScript"
|
|
Write-Host ""
|
|
Write-Host "Press any key to continue to command prompt..." -ForegroundColor Yellow
|
|
$null = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
|
}
|
|
}
|
|
else {
|
|
Write-Host "To use this WinPE environment:" -ForegroundColor White
|
|
Write-Host " 1. Insert USB drive or external media" -ForegroundColor Cyan
|
|
Write-Host " 2. Create folder: [$ScriptsFolder] in root" -ForegroundColor Cyan
|
|
Write-Host " 3. Add script: [$TargetScript]" -ForegroundColor Cyan
|
|
Write-Host " 4. Reboot or run this launcher again" -ForegroundColor Cyan
|
|
Write-Host ""
|
|
Write-Host "OR" -ForegroundColor Yellow
|
|
Write-Host ""
|
|
Write-Host " Create folder: X:\$ScriptsFolder on this WinPE image" -ForegroundColor Cyan
|
|
Write-Host " Add your scripts and run this launcher again" -ForegroundColor Cyan
|
|
Write-Host ""
|
|
Write-Host "Press any key to continue to command prompt..." -ForegroundColor Yellow
|
|
$null = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
|
|
}
|
|
}
|