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>
201 lines
6.1 KiB
PowerShell
201 lines
6.1 KiB
PowerShell
#Requires -Version 5.1
|
|
#Requires -RunAsAdministrator
|
|
<#
|
|
.SYNOPSIS
|
|
Updates PowerShell modules in the repository for WinPE integration.
|
|
|
|
.DESCRIPTION
|
|
Downloads or updates PowerShell modules from PSGallery to the modules/ directory.
|
|
These modules are then committed to the repository and included in WinPE builds.
|
|
|
|
.PARAMETER ModuleName
|
|
Name of a specific module to update. If not specified, updates all modules in config.json.
|
|
|
|
.PARAMETER Force
|
|
Forces re-download even if module already exists.
|
|
|
|
.EXAMPLE
|
|
.\Update-Modules.ps1
|
|
Updates all modules listed in config.json
|
|
|
|
.EXAMPLE
|
|
.\Update-Modules.ps1 -ModuleName "PSWindowsUpdate" -Force
|
|
Forces update of specific module
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$ModuleName,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[switch]$Force
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$ConfigPath = Join-Path $PSScriptRoot "config.json"
|
|
$ModulesRoot = Join-Path $PSScriptRoot "modules"
|
|
|
|
function Write-Status {
|
|
param(
|
|
[string]$Message,
|
|
[string]$Type = "Info"
|
|
)
|
|
|
|
$color = switch ($Type) {
|
|
"Success" { "Green" }
|
|
"Warning" { "Yellow" }
|
|
"Error" { "Red" }
|
|
"Info" { "Cyan" }
|
|
default { "White" }
|
|
}
|
|
|
|
$prefix = switch ($Type) {
|
|
"Success" { "[+]" }
|
|
"Warning" { "[!]" }
|
|
"Error" { "[X]" }
|
|
"Info" { "[i]" }
|
|
default { "[-]" }
|
|
}
|
|
|
|
Write-Host "$prefix " -ForegroundColor $color -NoNewline
|
|
Write-Host $Message
|
|
}
|
|
|
|
function Get-ConfiguredModules {
|
|
if (-not (Test-Path $ConfigPath)) {
|
|
throw "Configuration file not found: $ConfigPath"
|
|
}
|
|
|
|
try {
|
|
$config = Get-Content $ConfigPath -Raw | ConvertFrom-Json
|
|
return $config.powershellModules
|
|
}
|
|
catch {
|
|
throw "Failed to read configuration: $_"
|
|
}
|
|
}
|
|
|
|
function Initialize-ModulesDirectory {
|
|
if (-not (Test-Path $ModulesRoot)) {
|
|
Write-Status "Creating modules directory: $ModulesRoot" "Info"
|
|
New-Item -ItemType Directory -Path $ModulesRoot | Out-Null
|
|
}
|
|
}
|
|
|
|
function Update-PSGalleryModule {
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Name
|
|
)
|
|
|
|
Write-Host ""
|
|
Write-Host "=" * 70 -ForegroundColor Cyan
|
|
Write-Status "Processing module: $Name" "Info"
|
|
Write-Host "=" * 70 -ForegroundColor Cyan
|
|
|
|
$modulePath = Join-Path $ModulesRoot $Name
|
|
|
|
if ((Test-Path $modulePath) -and -not $Force) {
|
|
Write-Status "Module already exists: $modulePath" "Warning"
|
|
Write-Status "Use -Force to re-download" "Info"
|
|
return
|
|
}
|
|
|
|
if (Test-Path $modulePath) {
|
|
Write-Status "Removing existing module..." "Warning"
|
|
Remove-Item $modulePath -Recurse -Force
|
|
}
|
|
|
|
Write-Status "Searching PSGallery for module: $Name" "Info"
|
|
|
|
try {
|
|
$moduleInfo = Find-Module -Name $Name -Repository PSGallery -ErrorAction Stop
|
|
|
|
Write-Status "Found: $Name v$($moduleInfo.Version)" "Success"
|
|
Write-Status "Description: $($moduleInfo.Description)" "Info"
|
|
|
|
if ($moduleInfo.Dependencies -and $moduleInfo.Dependencies.Count -gt 0) {
|
|
Write-Status "Dependencies detected:" "Warning"
|
|
foreach ($dep in $moduleInfo.Dependencies) {
|
|
Write-Host " - $($dep.Name)" -ForegroundColor Yellow
|
|
}
|
|
Write-Status "Dependencies will be downloaded automatically" "Info"
|
|
}
|
|
|
|
Write-Status "Downloading module to repository..." "Info"
|
|
|
|
Save-Module -Name $Name -Path $ModulesRoot -Repository PSGallery -Force
|
|
|
|
if (Test-Path $modulePath) {
|
|
$savedVersion = (Get-ChildItem $modulePath -Directory | Select-Object -First 1).Name
|
|
Write-Status "Successfully saved: $Name v$savedVersion" "Success"
|
|
|
|
$moduleSizeMB = (Get-ChildItem $modulePath -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB
|
|
Write-Status "Module size: $([math]::Round($moduleSizeMB, 2)) MB" "Info"
|
|
}
|
|
else {
|
|
throw "Module save completed but directory not found"
|
|
}
|
|
}
|
|
catch {
|
|
Write-Status "Failed to update module: $Name" "Error"
|
|
Write-Status "Error: $($_.Exception.Message)" "Error"
|
|
throw
|
|
}
|
|
}
|
|
|
|
try {
|
|
Write-Host ""
|
|
Write-Host "================================================" -ForegroundColor Cyan
|
|
Write-Host " PowerShell Module Repository Updater" -ForegroundColor Yellow
|
|
Write-Host "================================================" -ForegroundColor Cyan
|
|
Write-Host ""
|
|
|
|
Initialize-ModulesDirectory
|
|
|
|
if ($ModuleName) {
|
|
Write-Status "Single module update requested: $ModuleName" "Info"
|
|
$modulesToUpdate = @($ModuleName)
|
|
}
|
|
else {
|
|
Write-Status "Reading configuration: $ConfigPath" "Info"
|
|
$modulesToUpdate = Get-ConfiguredModules
|
|
|
|
if ($null -eq $modulesToUpdate -or $modulesToUpdate.Count -eq 0) {
|
|
Write-Status "No modules configured in config.json" "Warning"
|
|
Write-Status "Add modules to 'powershellModules' array in config.json" "Info"
|
|
exit 0
|
|
}
|
|
|
|
Write-Status "Found $($modulesToUpdate.Count) module(s) in configuration" "Success"
|
|
}
|
|
|
|
Write-Host ""
|
|
|
|
foreach ($module in $modulesToUpdate) {
|
|
Update-PSGalleryModule -Name $module
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "================================================" -ForegroundColor Green
|
|
Write-Status "Module update completed successfully" "Success"
|
|
Write-Host "================================================" -ForegroundColor Green
|
|
Write-Host ""
|
|
Write-Status "Modules saved to: $ModulesRoot" "Info"
|
|
Write-Status "These modules will be included in the next WinPE build" "Info"
|
|
Write-Host ""
|
|
|
|
Write-Host "Next steps:" -ForegroundColor Yellow
|
|
Write-Host " 1. Review downloaded modules in: $ModulesRoot" -ForegroundColor Cyan
|
|
Write-Host " 2. Commit changes to git if desired" -ForegroundColor Cyan
|
|
Write-Host " 3. Run Build-PE.ps1 to create updated WinPE image" -ForegroundColor Cyan
|
|
Write-Host ""
|
|
}
|
|
catch {
|
|
Write-Host ""
|
|
Write-Status "FATAL ERROR: $($_.Exception.Message)" "Error"
|
|
Write-Host ""
|
|
exit 1
|
|
}
|