--- title: Architecture & Design weight: 1 toc: true --- ## Overview Winutil is a PowerShell-based Windows utility with a WPF (Windows Presentation Foundation) GUI. This document explains the architecture, code structure, and how different components work together. ## High-Level Architecture ``` ┌─────────────────────────────────────────────────────┐ │ Winutil GUI │ │ (WPF XAML Interface) │ └──────────────────┬──────────────────────────────────┘ │ ┌─────────┴─────────┐ │ │ ┌────────▼──────┐ ┌───────▼────────┐ │ Public APIs │ │ Private APIs │ │ (User-facing)│ │ (Internal) │ └───────┬───────┘ └───────┬────────┘ │ │ └────────┬──────────┘ │ ┌────────────▼────────────┐ │ Configuration Files │ │ (JSON definitions) │ └────────────┬────────────┘ │ ┌────────────▼────────────┐ │ External Tools │ │ (WinGet, Chocolatey) │ └─────────────────────────┘ ``` ## Project Structure ### Directory Layout ``` winutil/ ├── Compile.ps1 # Build script that combines all files ├── winutil.ps1 # Compiled output (generated) ├── scripts/ │ ├── main.ps1 # Entry point and GUI initialization │ └── start.ps1 # Startup logic ├── functions/ │ ├── private/ # Internal helper functions │ │ ├── Get-WinUtilVariables.ps1 │ │ ├── Install-WinUtilWinget.ps1 │ │ └── ... │ ├── public/ # User-facing functions │ │ ├── Initialize-WPFUI.ps1 │ │ └── ... │ └── microwin/ # MicroWin specific functions │ ├── Invoke-Microwin.ps1 │ └── ... ├── config/ # JSON configuration files │ ├── applications.json # Application definitions │ ├── tweaks.json # Tweak definitions │ ├── feature.json # Windows feature definitions │ └── preset.json # Preset configurations ├── xaml/ │ └── inputXML.xaml # GUI layout definition └── docs/ # Documentation ``` ### Key Components #### 1. Compile.ps1 **Purpose**: Combines all separate script files into a single `winutil.ps1` for distribution. **Process**: 1. Reads all function files from `/functions/` 2. Includes configuration JSON files 3. Embeds XAML GUI definition 4. Combines into single script 5. Outputs `winutil.ps1` **Why**: Makes distribution easier (single file) and improves load time. #### 2. scripts/main.ps1 **Purpose**: Entry point that initializes the GUI and event system. **Responsibilities**: - Load XAML and create WPF window - Initialize form elements - Set up event handlers - Load configurations - Display the GUI #### 3. functions/public/ **Purpose**: User-facing functions that implement main features. **Key Functions**: - `Initialize-WPFUI.ps1`: Sets up the GUI - `Invoke-WPFTweak*`: Applies system tweaks - `Invoke-WPFFeature*`: Enables Windows features - `Install-WinUtilProgram*`: Installs applications **Naming Convention**: Functions start with `WPF` or `Winutil` to be loaded into the runspace. #### 4. functions/private/ **Purpose**: Internal helper functions not directly called by users. **Key Functions**: - `Get-WinUtilVariables.ps1`: Retrieves UI element references - `Install-WinUtilWinget.ps1`: Ensures WinGet is installed - `Get-WinUtilCheckBoxes.ps1`: Gets checkbox states - `Invoke-WinUtilCurrentSystem.ps1`: Gets system information #### 5. config/*.json **Purpose**: Define available applications, tweaks, and features declaratively. **Files**: - `applications.json`: Application definitions with WinGet/Choco IDs - `tweaks.json`: Registry tweaks and their undo actions - `feature.json`: Windows features that can be enabled/disabled - `preset.json`: Predefined tweak combinations - `dns.json`: DNS provider configurations #### 6. xaml/inputXML.xaml **Purpose**: WPF GUI layout and design. **Structure**: - TabControl for main tabs (Install, Tweaks, Config, MicroWin) - Buttons with event handlers - TextBoxes for input - CheckBoxes for options - ListBoxes for selections ## Data Flow ### Application Installation Flow ``` User clicks "Install" ↓ Get-WinUtilCheckBoxes → Retrieves selected apps ↓ For each selected app: ↓ Check if WinGet/Choco installed ↓ Install-WinUtilWinget/Choco (if needed) ↓ Install-WinUtilProgramWinget/Choco → Install app ↓ Update UI with progress ↓ Display completion message ``` ### Tweak Application Flow ``` User selects tweaks and clicks "Run Tweaks" ↓ Get-WinUtilCheckBoxes → Get selected tweaks ↓ For each selected tweak: ↓ Load tweak definition from tweaks.json ↓ Invoke-WPFTweak → Apply registry/service changes ↓ Log changes ↓ Store original values (for undo) ↓ Update UI ↓ Display completion ``` ### Undo Tweak Flow ``` User selects tweaks and clicks "Undo" ↓ Get-WinUtilCheckBoxes → Get selected tweaks ↓ For each tweak: ↓ Retrieve "OriginalState" from tweak definition ↓ Invoke-WPFUndoTweak → Restore original values ↓ Remove from applied tweaks log ↓ Update UI ``` ## Configuration File Format ### applications.json Structure ```json { "WPFInstall": { "category": "Browsers", "choco": "googlechrome", "content": "Google Chrome", "description": "Google Chrome browser", "link": "https://chrome.google.com", "winget": "Google.Chrome" } } ``` **Fields**: - `category`: Which section in the Install tab - `content`: Display name in GUI - `description`: Tooltip/description text - `winget`: WinGet package ID - `choco`: Chocolatey package name - `link`: Official website ### tweaks.json Structure ```json { "WPFTweaksTelemetry": { "Content": "Disable Telemetry", "Description": "Disables Microsoft Telemetry", "category": "Essential Tweaks", "panel": "1", "Order": "a003_", "registry": [ { "Path": "HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows\\DataCollection", "Name": "AllowTelemetry", "Type": "DWord", "Value": "0", "OriginalValue": "1" } ], "ScheduledTask": [ { "Name": "Microsoft\\Windows\\Autochk\\Proxy", "State": "Disabled", "OriginalState": "Enabled" } ] } } ``` **Fields**: - `Content`: Display name - `Description`: What it does - `category`: Essential/Advanced/Customize - `registry`: Registry changes to make - `ScheduledTask`: Scheduled tasks to modify - `service`: Services to change - `OriginalValue/State`: For undo functionality ## PowerShell Runspace Winutil uses PowerShell runspaces for the GUI to remain responsive: ```powershell # Create runspace $sync.runspace = [runspacefactory]::CreateRunspace() $sync.runspace.Open() $sync.runspace.SessionStateProxy.SetVariable("sync", $sync) # Run code in background $powershell = [powershell]::Create().AddScript($scriptblock) $powershell.Runspace = $sync.runspace $handle = $powershell.BeginInvoke() ``` **Why**: Prevents UI freezing during long-running operations. ## WPF Event Handling Events are wired up via XAML element names: ```powershell # Get all named elements $sync.keys | ForEach-Object { if($sync.$_.GetType().Name -eq "Button") { $sync.$_.Add_Click({ $button = $sync.$($args[0].Name) & "Invoke-$($args[0].Name)" }) } } ``` **Convention**: Button named `WPFInstallButton` calls function `Invoke-WPFInstallButton`. ## Package Manager Integration ### WinGet Integration ```powershell # Check if installed if (!(Get-Command winget -ErrorAction SilentlyContinue)) { Install-WinUtilWinget } # Install package winget install --id $app.winget --silent --accept-source-agreements ``` ### Chocolatey Integration ```powershell # Check if installed if (!(Get-Command choco -ErrorAction SilentlyContinue)) { Install-WinUtilChoco } # Install package choco install $app.choco -y ``` ## MicroWin Architecture MicroWin operates in phases: 1. **Mount ISO**: Extract Windows image 2. **Modify Image**: Remove components, apply tweaks 3. **Inject Drivers**: Add custom drivers (optional) 4. **Create Unattend**: Generate automated install configuration 5. **Rebuild ISO**: Package modified image into new ISO **Key Files**: - `Invoke-Microwin.ps1`: Main orchestration - `Microwin-RemovePackages.ps1`: Remove Windows packages - `Microwin-RemoveFeatures.ps1`: Disable features - `Microwin-NewUnattend.ps1`: Create unattend.xml ## Error Handling Winutil uses PowerShell error handling: ```powershell try { # Attempt operation Invoke-SomeOperation } catch { Write-Host "Error: $_" -ForegroundColor Red # Log error Add-Content -Path $logfile -Value "ERROR: $_" } ``` **Logging**: Errors and operations are logged for debugging. ## Configuration Loading At startup, Winutil loads all configurations: ```powershell # Load JSON configs $sync.configs = @{} $sync.configs.applications = Get-Content "config/applications.json" | ConvertFrom-Json $sync.configs.tweaks = Get-Content "config/tweaks.json" | ConvertFrom-Json $sync.configs.features = Get-Content "config/feature.json" | ConvertFrom-Json ``` **Sync Hash**: `$sync` hashtable shares state across runspaces. ## UI Update Pattern UI updates must happen on the UI thread: ```powershell $sync.form.Dispatcher.Invoke([action]{ $sync.WPFStatusLabel.Content = "Installing..." }, "Normal") ``` **Why**: WPF requires UI updates on the main thread. ## Adding New Features ### Adding a New Application 1. Edit `config/applications.json`: ```json { "WPFInstallNewApp": { "category": "Utilities", "content": "New App", "description": "Description of new app", "winget": "Publisher.AppName", "choco": "appname" } } ``` 2. Recompile: `.\Compile.ps1` 3. The app appears automatically in Install tab ### Adding a New Tweak 1. Edit `config/tweaks.json`: ```json { "WPFTweaksNewTweak": { "Content": "New Tweak", "Description": "What it does", "category": "Essential Tweaks", "registry": [ { "Path": "HKLM:\\Path\\To\\Key", "Name": "ValueName", "Type": "DWord", "Value": "1", "OriginalValue": "0" } ] } } ``` 2. Recompile: `.\Compile.ps1` 3. Tweak appears in Tweaks tab ### Adding a New Function 1. Create file in `functions/public/` or `functions/private/`: ```powershell # functions/public/Invoke-WPFNewFeature.ps1 function Invoke-WPFNewFeature { <# .SYNOPSIS Does something new #> # Implementation } ``` 2. File naming must include "WPF" or "Winutil" to load 3. Recompile: `.\Compile.ps1` ## Testing ### Manual Testing ```powershell # Compile and run with -run flag .\Compile.ps1 -run ``` ### Automated Tests Tests are in `/pester/`: - `configs.Tests.ps1`: Validates JSON configurations - `functions.Tests.ps1`: Tests PowerShell functions Run tests: ```powershell Invoke-Pester ``` ## Build Process ### Development Build ```powershell .\Compile.ps1 ``` Outputs `winutil.ps1` in the root directory. ### Production Release 1. Tag release in Git 2. GitHub Actions builds and uploads `winutil.ps1` 3. Release appears on GitHub Releases 4. Users download via `irm christitus.com/win` ## Dependencies **Required**: - PowerShell 5.1+ - .NET Framework 4.5+ - Windows 10 1809+ **Optional (auto-installed)**: - WinGet (Windows Package Manager) - Chocolatey - oscdimg.exe (for MicroWin) ## Performance Considerations **Optimization Strategies**: - Lazy-load configurations (only when needed) - Use runspaces for long operations - Cache expensive lookups - Minimize registry reads/writes - Batch operations when possible ## Security Considerations **Safety Measures**: - All operations logged - Registry backups for undo - No credential storage - Open source (auditable) - Digitally signed (future) ## Contributing Guidelines **Code Standards**: - Use proper PowerShell cmdlet naming (Verb-Noun) - Include comment-based help - Follow existing code style - Test thoroughly before PR - Document significant changes **File Naming**: - Public functions: `Invoke-WPF*.ps1` or `Invoke-Winutil*.ps1` - Private functions: `Get-WinUtil*.ps1` or verb-WinUtil*.ps1` - Must include "WPF" or "Winutil" to load ## Future Architecture Plans **Roadmap Considerations**: - Plugin system for community extensions - Config import/export - Cloud sync for configurations - Enhanced logging dashboard - Modular compilation (choose features) ## Related Documentation - [Contributing Guide](../../contributing/) - How to contribute code - [User Guide](../../userguide/) - End-user documentation - [FAQ](../../faq/) - Common questions ## Additional Resources - **GitHub Repository**: [ChrisTitusTech/winutil](https://github.com/ChrisTitusTech/winutil) - **PowerShell Docs**: [Microsoft Docs](https://docs.microsoft.com/powershell/) - **WPF Guide**: [WPF Documentation](https://docs.microsoft.com/dotnet/desktop/wpf/) --- **Last Updated**: January 2026 **Maintainers**: Chris Titus Tech and contributors