build-pe-script-launcher/CLAUDE.md

427 lines
14 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Repository Information
**Git Repository:** https://git.farmtowntech.com/setonc/build-pe-script-launcher
**Branch:** master
**Status:** Active development
```powershell
# Clone the repository
git clone https://git.farmtowntech.com/setonc/build-pe-script-launcher.git
```
## Project Overview
Build PE Script Launcher - A production-grade Windows PE builder that creates bootable images with PowerShell 7, custom modules, and automatic script launching from external media. The PE image remains static; rebuilds are only needed for PowerShell 7 or module updates.
## Quick Start
```powershell
# Clone and build
.\Build-PE.ps1
# Update PowerShell modules (optional)
.\Update-Modules.ps1
# Test the ISO in a VM
# Boot WinPE.iso with external media containing .scripts folder
```
## Architecture
### Core Components
**Build-PE.ps1** - Main orchestrator
- Validates dependencies (auto-installs Windows ADK if missing)
- Downloads PowerShell 7 if needed
- Mounts WinPE image via DISM
- Integrates PowerShell 7 and modules
- Injects launcher scripts
- Creates bootable ISO
**config.json** - Configuration
- PowerShell modules list
- Target script name
- Scripts folder name
- PowerShell 7 version and download URL
**lib/** - Build modules
- `Dependencies.psm1` - ADK validation and auto-installation
- `WinPEBuilder.psm1` - DISM operations (mount, unmount, add packages)
- `PowerShell7.psm1` - PS7 extraction and integration
- `ModuleManager.psm1` - Module copying to WinPE image
**resources/** - Runtime scripts
- `Invoke-ScriptLauncher.ps1` - Runs on PE boot, scans for external media
- `Invoke-ScriptMenu.ps1` - Fallback menu for local .scripts folder
**modules/** - PowerShell modules
- Pre-downloaded modules from PSGallery
- Committed to repository for offline builds
- Updated via `Update-Modules.ps1`
### Boot Flow
```
WinPE Boot
startnet.cmd (modified)
Console window maximizes automatically
Invoke-ScriptLauncher.ps1 (PowerShell 7)
Scans all drives for .scripts folder
├─ Found on external media?
│ ↓
│ Execute configured target script
│ (e.g., user's custom Invoke-ScriptMenu.ps1)
└─ Not found?
Check for local X:\.scripts
├─ Found? → Launch Invoke-ScriptMenu.ps1
└─ Not found? → Show instructions, drop to PowerShell 7 prompt
```
**Console Features:**
- **PowerShell 7 by default** - All scripts and the command prompt use PS7
- **Maximized window** - Console automatically maximizes on boot for full-screen experience
- **Elevated privileges** - Everything runs as SYSTEM (no UAC in WinPE)
- **Classic UI** - WinPE uses legacy console rendering (no modern W10/W11 decorations available)
### Build Process Workflow
1. **Dependency Check** - Validates admin rights, ADK installation, PS7 availability
2. **Workspace Init** - Creates work directory using ADK's copype.cmd
3. **Mount Image** - Mounts boot.wim for modification
4. **Add Components** - Installs WinPE optional components (WMI, NetFX, PowerShell, etc.)
5. **Install PS7** - Extracts PowerShell 7 to `Program Files\PowerShell\7`
6. **Copy Modules** - Copies modules from repository to image
7. **Inject Scripts** - Copies launcher and menu scripts to System32
8. **Configure Startup** - Modifies startnet.cmd to run launcher
9. **Unmount** - Commits changes and unmounts image
10. **Create ISO** - Generates bootable ISO using MakeWinPEMedia
## Configuration
### config.json Structure
```json
{
"powershellModules": ["ModuleName1", "ModuleName2"],
"targetScript": "Invoke-ScriptMenu.ps1",
"scriptsFolder": ".scripts",
"startupScript": "Invoke-ScriptLauncher.ps1",
"fallbackScript": "Invoke-ScriptMenu.ps1",
"consoleColors": {
"backgroundColor": "Black",
"foregroundColor": "Gray"
},
"powershell7Version": "7.4.13",
"powershell7ZipUrl": "https://github.com/PowerShell/PowerShell/releases/..."
}
```
**Configuration Options:**
**powershellModules** - Array of module names to include in WinPE (from PSGallery)
**targetScript** - Script name to execute from external media .scripts folder
**scriptsFolder** - Name of folder to search for on external media (default: ".scripts")
**startupScript** - Script that runs first on boot (default: "Invoke-ScriptLauncher.ps1")
- Must exist in resources/ folder
- This is the entry point for your WinPE environment
**fallbackScript** - Script embedded in image for offline/local use (default: "Invoke-ScriptMenu.ps1")
- Must exist in resources/ folder
- Runs when no external media is found but X:\.scripts exists
**consoleColors** - Customize PowerShell console appearance
- backgroundColor: Console background color (Black, DarkBlue, DarkGreen, etc.)
- foregroundColor: Console text color (Gray, White, Cyan, etc.)
**powershell7Version** - Version of PowerShell 7 to integrate
**powershell7ZipUrl** - Direct download URL for PS7 zip archive
## Commands
### Build WinPE Image
```powershell
.\Build-PE.ps1
```
First run downloads Windows ADK (~4GB, 20-30 min), subsequent builds are faster (~10 min).
Options:
- `-CleanBuild` - Remove existing work directory
- `-SkipADKCheck` - Skip ADK validation (not recommended)
- `-DefenderOptimization <Mode>` - Optimize Windows Defender for faster builds (see Performance Optimization below)
### Build with Performance Optimization
Windows Defender real-time scanning significantly impacts DISM performance. Use `-DefenderOptimization` for faster builds:
```powershell
# Fastest: Temporarily disable real-time protection (50-70% improvement)
.\Build-PE.ps1 -DefenderOptimization DisableRealTime
# Balanced: Add build directories to exclusions (20-30% improvement)
.\Build-PE.ps1 -DefenderOptimization AddExclusions
# Default: No Defender changes (safest)
.\Build-PE.ps1 -DefenderOptimization None
```
**Defender optimization modes:**
- `None` (default) - No changes to Defender, safest option
- `DisableRealTime` - Temporarily disable real-time protection for build duration, restored automatically (fastest)
- `AddExclusions` - Add build directories and ADK paths to Defender exclusions, removed after build (balanced)
**Note:** Defender settings are automatically restored when the build completes, even if it fails.
### Update Modules
```powershell
# Update all modules in config.json
.\Update-Modules.ps1
# Update specific module
.\Update-Modules.ps1 -ModuleName "PSWindowsUpdate"
# Force re-download
.\Update-Modules.ps1 -ModuleName "PSWindowsUpdate" -Force
```
## Directory Structure
```
Build PE Script Launcher/
├── Build-PE.ps1 # Main build script
├── Update-Modules.ps1 # Module updater utility
├── config.json # Build configuration
├── lib/ # Build-time modules
│ ├── Dependencies.psm1
│ ├── WinPEBuilder.psm1
│ ├── PowerShell7.psm1
│ ├── ModuleManager.psm1
│ └── DefenderOptimization.psm1
├── resources/ # Runtime scripts
│ ├── Invoke-ScriptLauncher.ps1
│ └── Invoke-ScriptMenu.ps1
├── modules/ # PowerShell modules (committed)
│ └── <ModuleName>/
├── work/ # Build workspace (gitignored)
│ ├── mount/ # Mounted WinPE image
│ └── media/ # WinPE media files
└── output/ # Build outputs (gitignored)
├── WinPE.iso
└── build.log
```
## Key Technical Details
### Windows ADK Integration
- Auto-installs via silent parameters: `/quiet /norestart /features OptionId.DeploymentTools`
- Installs both ADK core and WinPE add-on
- Uses `copype.cmd` to create initial WinPE workspace
- Uses `MakeWinPEMedia.cmd` to create bootable ISO
### PowerShell 7 Integration
- Based on community method (not officially supported by Microsoft)
- Extracts PS7 portable zip to `X:\Program Files\PowerShell\7`
- Modifies startnet.cmd to add PS7 to PATH
- Uses PowerShell 7 LTS (v7.4.13) for 3-year support
### DISM Operations
All image modifications use DISM commands:
- Mount: `dism /Mount-Image /ImageFile:boot.wim /Index:1 /MountDir:mount`
- Add package: `dism /Add-Package /Image:mount /PackagePath:package.cab`
- Unmount: `dism /Unmount-Image /MountDir:mount /Commit`
### Module Management
- Modules stored in `modules/` using `Save-Module` structure
- Copied to `X:\Program Files\WindowsPowerShell\Modules\` in image
- Dependencies automatically resolved by `Update-Modules.ps1`
## Troubleshooting
### Build fails with "Image is already mounted"
```powershell
dism /Cleanup-Mountpoints
```
### ADK installation fails
- Check internet connection
- Ensure sufficient disk space (~10GB)
- Run as Administrator
### Module not found during build
```powershell
# Download missing module
.\Update-Modules.ps1 -ModuleName "ModuleName"
# Or verify config.json module names match PSGallery exactly
```
### PowerShell 7 not in PATH when PE boots
- Check startnet.cmd modification in mounted image
- Verify PS7 extracted to correct path
- Review build.log for errors
## Modifying the Project
### Adding a New Module
1. Add module name to `config.json` powershellModules array
2. Run `.\Update-Modules.ps1 -ModuleName "NewModule"`
3. Rebuild: `.\Build-PE.ps1`
### Changing Scripts
**External Media Script (runs from USB/external drive):**
1. Modify `targetScript` in `config.json`
2. Ensure your script exists in external media's .scripts folder
3. Rebuild: `.\Build-PE.ps1`
**Startup Script (first script that runs on boot):**
1. Create your custom script in `resources/` folder
2. Update `startupScript` in `config.json` with your script name
3. Rebuild: `.\Build-PE.ps1`
4. Script must handle external media detection or call other scripts
**Fallback Script (embedded for offline use):**
1. Create your custom script in `resources/` folder
2. Update `fallbackScript` in `config.json` with your script name
3. Rebuild: `.\Build-PE.ps1`
4. Script will be available at X:\Windows\System32\ when no external media found
### Customizing Console Colors
1. Edit `consoleColors` in `config.json`
2. Choose from: Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan, Red, Magenta, Yellow, White
3. Rebuild: `.\Build-PE.ps1`
Example - Dark blue theme:
```json
"consoleColors": {
"backgroundColor": "DarkBlue",
"foregroundColor": "White"
}
```
### Upgrading PowerShell 7
1. Update `powershell7Version` and `powershell7ZipUrl` in config.json
2. Delete old PowerShell zip file
3. Rebuild: `.\Build-PE.ps1`
### Customizing Launcher Behavior
Edit `resources/Invoke-ScriptLauncher.ps1`:
- Change drive scanning logic
- Modify error messages
- Add additional checks
- Customize banner display
## Use Cases
### Driver Extraction from Offline Windows
User boots WinPE → Launcher finds .scripts on USB → Runs driver export script
### System Recovery Scripts
Multiple recovery scripts on external media → Menu lets user choose → Script runs with PS7 and modules available
### Automated Deployment
Pre-configured script on known media → Launcher auto-executes → Unattended deployment
## External Media Setup
### For End Users
1. Format USB drive
2. Create `.scripts` folder in root
3. Add target script (e.g., `Invoke-ScriptMenu.ps1`)
4. Add additional scripts
5. Boot WinPE image
### Example .scripts Structure
```
USB:\
└── .scripts\
├── Invoke-ScriptMenu.ps1 # Entry point
├── Export-Drivers.ps1
├── Backup-System.ps1
└── utilities\
└── helpers.psm1
```
## Performance Notes
### Build Times (without optimization)
- First build: 30-45 minutes (ADK download + install)
- Subsequent builds: 5-10 minutes
- ISO size: ~500MB
- Module impact: ~10-50MB per module typically
### Windows Defender Optimization
Windows Defender real-time scanning significantly impacts DISM and ADK performance. Use `-DefenderOptimization` for dramatic speed improvements:
**Performance Impact by Mode:**
| Mode | First Build | Subsequent | Improvement | Risk Level |
|------|-------------|------------|-------------|------------|
| None (default) | 30-45 min | 5-10 min | Baseline | Safest |
| AddExclusions | 24-32 min | 4-7 min | 20-30% faster | Low |
| DisableRealTime | 15-20 min | 2-4 min | 50-70% faster | Low* |
*DisableRealTime temporarily disables protection but automatically restores it when build completes (even on failure).
**Which mode to use:**
- **Development:** Use `DisableRealTime` for fastest builds
- **CI/CD pipelines:** Use `AddExclusions` for good performance with minimal risk
- **Production/Shared systems:** Use `None` (default) for safety
- **Enterprise:** Use `AddExclusions` with approval from security team
**How it works:**
- `DisableRealTime` - Temporarily disables Windows Defender real-time protection during build, restores original state when done
- `AddExclusions` - Adds work/, downloads/, output/, and ADK paths to Defender exclusions during build, removes them when done
- `None` - No changes to Defender (default behavior)
All Defender changes are automatically reverted when the build completes, even if the build fails.
## Security Considerations
- Scripts run with SYSTEM privileges in WinPE
- No execution policy restrictions
- Only use trusted scripts
- Validate all external media scripts before use
- Consider signing scripts for enterprise deployment
- **Defender Optimization:** When using `-DefenderOptimization`, Defender settings are automatically restored after build. Even if build fails, the finally block ensures restoration. Safe for development use.
## Known Limitations
- PowerShell 7 in WinPE is unofficial (works but unsupported)
- Some cmdlets (Get-PhysicalDisk) may not work under PS7 in WinPE
- UAC not present in WinPE (all scripts run elevated)
- Network drivers may need manual addition for some hardware
- **UI Limitations:**
- Console uses legacy Windows console rendering (no modern W10/W11 window decorations)
- WinPE lacks DWM (Desktop Window Manager) and modern shell components
- True borderless fullscreen not available; window maximization is the best alternative
- No Aero, Fluent Design, or modern theming support