Jesse A. Green / notebook

Chris Titus Tech's Windows Utility (WinUtil) — Admin & Developer Guide

Generated June 2026 from ChrisTitusTech/winutil at e83033a

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide is for administrators, architects, and contributors who need to understand how WinUtil is built and how it behaves on a managed system. It covers the build pipeline, runtime architecture, the configuration-driven UI engine, every category of system change WinUtil makes, security considerations, deployment/automation, and the repository internals needed to extend or audit the tool.

For end-user installation and usage, see the companion User Guide.


1. Executive Summary

WinUtil is a single-file PowerShell + WPF desktop application for post-install Windows 11 administration. It is configuration-driven: the application catalog, tweaks, optional features, presets, themes, and DNS providers all live in JSON files under config/, and the GUI is generated dynamically from those JSON definitions at runtime. There is no compiled binary and no installer — distribution is a single winutil.ps1 script fetched from GitHub releases and executed in memory.

Attribute Value
Language / UI PowerShell 5.1+ / WPF (PresentationFramework) + WinForms helpers
Distribution Single winutil.ps1 (built by Compile.ps1); run via irm https://christitus.com/win | iex
Target OS Windows 11 (Windows 10 EOL 2025-10-14); Server/LTSC with caveats
Privileges Requires Administrator; self-elevates on launch
Concurrency RunspacePool (1 → $env:NUMBER_OF_PROCESSORS threads) with a synchronized $sync hashtable
Config model JSON files in config/ define apps, tweaks, features, presets, themes, DNS, navigation
Persistence None on the host except logs and a working dir under %LocalAppData%\winutil
Source repo https://github.com/ChrisTitusTech/winutil (MIT-licensed core)
This revision Commit e83033a, 239 files, ~257 KB of source, medium complexity tier

Design philosophy: keep the engine tiny and data-driven. Adding an app or a tweak means editing JSON, not PowerShell. The PowerShell layer is a generic interpreter that renders the JSON into WPF controls and dispatches each control's data (registry entries, services, appx names, scripts) to a small set of apply functions.

Important

WinUtil's user-facing surface area is defined almost entirely by config/*.json and xaml/inputXML.xaml. Static code analysis of the PowerShell alone will under-report what the tool does — the JSON is the specification. AST extraction over this repo yields essentially nothing; the configuration files are the source of truth.


2. Architecture

2.1 Build-time: compilation into a single script

WinUtil ships as one file, winutil.ps1, assembled by Compile.ps1 at the repo root. The build concatenates, in order:

  1. scripts/start.ps1 — the preamble (parameters, elevation, $sync bootstrap, logging). The build replaces the #{replaceme} version token with the current date (yy.MM.dd).
  2. Every *.ps1 under functions/ (recursively) — all private and public functions.
  3. Each config/*.json, embedded as a here-string and parsed back with ConvertFrom-Json into $sync.configs.<name>. For applications.json, every key is prefixed with WPFInstall so app keys become control names (e.g. chrome → WPFInstallchrome).
  4. xaml/inputXML.xaml — embedded as $inputXML.
  5. tools/autounattend.xml — embedded as $WinUtilAutounattendXml (used by MicroWin).
  6. scripts/main.ps1 — the GUI bootstrapper and event wiring (runs last).
Compile.ps1
  ├── scripts/start.ps1            (params, elevation, $sync, logging)
  ├── functions/**/*.ps1           (private + public functions)
  ├── config/*.json   ──embed──▶   $sync.configs.<name>
  ├── xaml/inputXML.xaml ─embed─▶   $inputXML
  ├── tools/autounattend.xml ──▶    $WinUtilAutounattendXml
  └── scripts/main.ps1             (load XAML, wire events, ShowDialog)
        └──▶ winutil.ps1  (single distributable file)

Compile.ps1 -Run builds and immediately launches the result. The windev.ps1 helper fetches and runs the latest pre-release winutil.ps1 from GitHub tags.

Note

Because the public release is a single generated file, the GitHub release winutil.ps1 is the only artifact end users ever execute. The config/, functions/, and xaml/ layout exists for development and is collapsed into that one file at build time.

2.2 Runtime: startup sequence

irm christitus.com/win | iex
        │
        ▼
scripts/start.ps1
  • parse params (-Config / -Preset / -Noui / -Offline)
  • verify FullLanguage mode (abort if Constrained)
  • verify Administrator; relaunch elevated via wt.exe / pwsh / powershell if not
  • Add-Type PresentationFramework + System.Windows.Forms
  • build synchronized $sync hashtable (selections, prefs, version)
  • create %LocalAppData%\winutil + \logs, Start-Transcript
        │
        ▼
(function bodies + embedded JSON/XAML are defined inline here)
        │
        ▼
scripts/main.ps1
  • print CTT ASCII banner; define PackageManagers enum (Winget, Choco)
  • create RunspacePool (1..NUMBER_OF_PROCESSORS) seeded with all winutil/WPF functions + $sync
  • define exception classes (WingetFailedInstall, ChocoFailedInstall, GenericException)
  • build applicationsHashtable; Set-Preferences
  • IF -Preset:  apply preset → Invoke-WinUtilAutoRun → exit (no GUI)
  • IF -Noui:    require -Config → import → Invoke-WinUtilAutoRun → exit
  • else: load XAML → bind named controls into $sync → render panels
          (Invoke-WPFUIElements for apps/tweaks/features) → wire events → ShowDialog

2.3 The $sync synchronized hashtable

$sync = [Hashtable]::Synchronized(@{}) is the single shared-state object across the main thread and all runspace threads. It holds:

  • $sync.configs.* — parsed JSON (applications, tweaks, feature, preset, dns, themes, appnavigation) plus applicationsHashtable.
  • $sync.Form and every named XAML element (each control with Name="X" is stored as $sync.X via FindName).
  • Selection lists: selectedApps, selectedTweaks, selectedToggles, selectedFeatures.
  • $sync.preferences (e.g. persisted packagemanager), $sync.ProcessRunning, $sync.currentTab, $sync.runspace (the RunspacePool), $sync.version.

Because it's a synchronized hashtable, background runspaces can safely read selections and update progress while the WPF thread owns the UI.

2.4 Concurrency model

Long-running work (installs, tweaks, feature installs) is dispatched to the RunspacePool via Invoke-WPFRunspace, which creates a [powershell] instance bound to $sync.runspace and BeginInvoke()s a scriptblock. UI updates from inside a runspace are marshaled back to the WPF dispatcher with Invoke-WPFUIThread ($sync.form.Dispatcher.Invoke). The $sync.ProcessRunning flag guards against starting overlapping operations and disables keyboard shortcuts while busy.

2.5 Component inventory

Component Location Responsibility
Build script Compile.ps1 Bundle config + xaml + functions → winutil.ps1
Entry preamble scripts/start.ps1 Params, elevation, $sync, logging
GUI bootstrap scripts/main.ps1 XAML load, event wiring, ShowDialog
UI definition xaml/inputXML.xaml WPF layout, styles, tab structure
App catalog config/applications.json Installable apps (winget/choco IDs, metadata)
Tweak definitions config/tweaks.json Registry/service/appx/script per tweak
Feature/Config buttons config/feature.json Config-tab features, fixes, panels
Presets config/preset.json Standard / Minimal / Advanced tweak sets
DNS providers config/dns.json IPv4/IPv6 server pairs
Themes config/themes.json Shared/Light/Dark color + sizing tokens
Install-tab nav config/appnavigation.json Action buttons, package-manager radios
UI engine functions/public/Invoke-WPFUIElements.ps1 Render JSON → WPF controls
Tweak engine functions/private/Invoke-WinUtilTweaks.ps1 Dispatch tweak data to apply functions
Apply primitives functions/private/Set-WinUtil*.ps1 Registry, service, DNS writes; appx removal
Install engine functions/private/Install-WinUtil*.ps1 winget/choco install/uninstall
MicroWin functions/private/Invoke-WinUtilISO*.ps1 Build custom Windows 11 ISO/USB
Tests pester/*.Tests.ps1 Pester validation of configs + functions
Lint config lint/PSScriptAnalyser.ps1 PSScriptAnalyzer settings
Docs generator tools/devdocs-generator.ps1 Generate Hugo docs from tweaks/feature JSON

3. The Configuration-Driven UI Engine

The heart of WinUtil is Invoke-WPFUIElements, a generic renderer that turns a JSON config object into WPF controls inside a named grid. main.ps1 calls it three times:

Invoke-WPFUIElements -configVariable $sync.configs.appnavigation -targetGridName "appscategory" -columncount 1
Invoke-WPFUIElements -configVariable $sync.configs.tweaks        -targetGridName "tweakspanel"  -columncount 2
Invoke-WPFUIElements -configVariable $sync.configs.feature       -targetGridName "featurespanel" -columncount 2

The engine organizes entries by Panel then Category, sorts each category (checkboxes → buttons → comboboxes, then alphabetically by Content), and emits a control based on each entry's Type:

Type Rendered control Behavior
(default / none) CheckBox + optional (?) link Adds/removes from a selection list on check
Toggle Colorful toggle switch Applies/undoes a tweak immediately via Invoke-WinUtilTweaks
Button Button Runs the mapped function/script on click
Combobox Label + ComboBox e.g. the DNS selector (ComboItems split on spaces)
RadioButton RadioButton (grouped by GroupName) e.g. WinGet/Chocolatey selector
ToggleButton ToggleButton with on/off content State-labeled buttons

Panels use virtualizing stack panels (VirtualizingStackPanel, recycling mode) for performance with large lists. The Install tab's app area is built separately by Initialize-InstallAppArea / Initialize-InstallCategoryAppList, which also use virtualization and a WrapPanel for responsive columns.

Tip

To add a tweak, app, or feature, you edit the relevant JSON file — no engine changes are needed. The control type, category placement, tooltip (Description), and docs link (link) all come from the JSON entry.

3.1 Button dispatch

Invoke-WPFButton resolves a clicked button in two stages:

  1. If the button name exists in config/feature.json and has a function or InvokeScript, run that.
  2. Otherwise fall back to a hard-coded switch mapping button names to functions (WPFInstall → Invoke-WPFInstall, WPFtweaksbutton → Invoke-WPFtweaksbutton, tab buttons → Invoke-WPFTab, preset buttons → Invoke-WPFPresets, etc.).

4. System Changes — What WinUtil Actually Does

This section is the audit-focused inventory of every category of change. All changes require Administrator rights.

4.1 Tweak application engine

Invoke-WinUtilTweaks -CheckBox <name> [-undo] [-KeepServiceStartup] reads the tweak's JSON definition and applies up to four kinds of change, choosing Value/StartupType/InvokeScript normally or OriginalValue/OriginalType/UndoScript when -undo is set:

JSON key Apply function Effect
service[] Set-WinUtilService Set each service's StartupType (Manual/Disabled/Automatic/AutomaticDelayedStart)
registry[] Set-WinUtilRegistry Create/set/remove a registry value (<RemoveEntry> deletes it)
InvokeScript[] / UndoScript[] Invoke-WinUtilScript Run an embedded PowerShell scriptblock
appx[] Remove-WinUtilAPPX Remove AppX/provisioned packages (apply only; not undone)

-KeepServiceStartup (default $true) skips changing a service whose current startup type no longer matches the recorded OriginalType, so WinUtil won't override a choice you (or another tool) deliberately made.

Set-WinUtilRegistry creates the key path if missing, mounts HKU: if needed, and either sets the value with the given Type (DWord/QWord/String/Binary) or removes it when the value is the sentinel <RemoveEntry>. Exceptions (security, unauthorized, not-found) are caught and logged as warnings rather than crashing the run.

4.2 Tweak catalog (config/tweaks.json)

Tweaks are grouped into four categories. Highlights of what each Essential tweak changes (all reversible via Undo unless noted):

Tweak Mechanism
Activity History – Disable Removes EnableActivityFeed/PublishUserActivities/UploadUserActivities policies
Telemetry – Disable ~12 registry values + disables DiagTrack/wermgr, opts out of PowerShell telemetry, Defender sample submission
Location Tracking – Disable Disables lfsvc, denies location consent, blocks sensor
Services – Set to Manual Manual/Disabled on several services + tunes SvcHostSplitThresholdInKB to RAM
Hibernation – Disable powercfg /hibernate off + registry (Undo re-enables)
ConsumerFeatures – Disable DisableWindowsConsumerFeatures policy
Delivery Optimization – Disable DODownloadMode=0
Unwanted Pre-Installed Apps – Remove (DeBloat) Removes ~19 AppX packages + uninstalls classic Teams
Disk Cleanup / Temporary Files Run cleanup / clear temp
End Task With Right Click Taskbar developer option
Restore Point – Create Creates a System Restore point (applied first when selected)
Widgets / Start Menu layout / Store search / Explorer auto-discovery / WPBT Various registry/appx/script changes

Advanced ("z__Advanced Tweaks – CAUTION") tweaks include Brave/Edge debloat, Remove Edge, Remove OneDrive, Remove File Explorer Home, Visual Effects → performance, Xbox removal, IPv6 preferences/disable, Teredo disable, background apps disable, fullscreen optimizations disable, Razer auto-install block, notifications disable, Adobe URL block, classic right-click menu, UTC clock, storage sense disable, Windows AI disable, O&O ShutUp10++, and the DNS selector.

Caution

Advanced tweaks make aggressive changes (removing Edge/OneDrive, disabling IPv6, blocking domains). Several download external helper tools at runtime (e.g. Revert Start Menu downloads ViVeTool; O&O ShutUp10++ downloads OOSU10.exe). Review the InvokeScript body in config/tweaks.json before deploying to managed fleets.

4.3 Customize Preferences (live toggles)

Toggle-type entries apply immediately on flip (and reverse on un-flip) through the same Invoke-WinUtilTweaks path. Examples: Dark mode, show file extensions/hidden files, taskbar alignment/search/task-view icons, Bing search in Start, Start recommendations, battery percentage, mouse acceleration, sticky keys, NumLock on startup, Game Mode, long paths, verbose logon, verbose BSoD, new Outlook, scrollbars, S0/S3 sleep, settings home page, logon acrylic blur. Their on/off state is read at render time via Get-WinUtilToggleStatus, which compares the live registry against the JSON-defined value.

4.4 Config-tab features & fixes (config/feature.json)

Entry Function / mechanism
.NET Framework / Hyper-V / WSL / NFS / Sandbox Enable-WindowsOptionalFeature via Invoke-WinUtilFeatureInstall (+ NFS InvokeScript for anonymous config)
Registry Backup / Legacy F8 Recovery bcdedit / scheduled-task InvokeScript
Windows Update – Reset Invoke-WPFFixesUpdate (stop services, clear caches, re-register 36 DLLs, reset policies, restart services)
Network – Reset Invoke-WPFFixesNetwork (netsh winsock reset, netsh int ip reset)
System Corruption Scan Invoke-WPFSystemRepair (chkdsk /scan, sfc /scannow, DISM /RestoreHealth)
WinGet – Reinstall Invoke-WPFFixesWinget → Install-WinUtilWinget
NTP Server – Enable w32tm repointed at pool.ntp.org
AutoLogon Downloads Sysinternals Autologon.exe
Legacy Windows Panels Launch control, compmgmt.msc, ncpa.cpl, powercfg.cpl, intl.cpl, rstrui.exe, mmsys.cpl, sysdm.cpl, timedate.cpl, printers shell
CTT PowerShell Profile – Install/Remove Invoke-WinUtilInstallPSProfile / ...Uninstall... (backs up existing $Profile)
OpenSSH Server – Enable Invoke-WinUtilSSHServer

4.5 Windows Update policies (Updates tab)

Function Behavior
Invoke-WPFUpdatesdefault Removes WinUtil's WU policy keys, restores BITS/wuauserv/UsoSvc/WaaSMedicSvc startup, re-enables WU scheduled tasks, resets local policy.
Invoke-WPFUpdatessecurity Defers feature updates 365 days, quality updates 4 days; sets BranchReadinessLevel=20; blocks driver offering; disables auto-restart with logged-on users.
Invoke-WPFUpdatesdisable NoAutoUpdate=1, disables BITS/wuauserv/UsoSvc, clears SoftwareDistribution, disables WU scheduled tasks. Blocks security updates.

4.6 Application install/uninstall

Invoke-WPFInstall / Invoke-WPFUnInstall resolve selected app keys to applicationsHashtable entries, sort them by manager via Get-WinUtilSelectedPackages (Chocolatey entries marked na fall back to WinGet), then run inside a runspace:

  • WinGet path: Install-WinUtilWinget (ensures WinGet present) → Install-WinUtilProgramWinget -Action Install/Uninstall.
  • Chocolatey path: Install-WinUtilChoco → Install-WinUtilProgramChoco -Action Install/Uninstall.

Invoke-WPFInstallUpgrade upgrades everything: winget upgrade --all --include-unknown --silent --accept-source-agreements --accept-package-agreements (or choco upgrade all -y). Invoke-WPFGetInstalled queries the system via Invoke-WinUtilCurrentSystem and ticks matching boxes.

4.7 DNS changes

Set-WinUtilDNS -DNSProvider <name> enumerates adapters in the Up state and calls Set-DnsClientServerAddress for both IPv4 and IPv6 using the pair from config/dns.json. Default is a no-op; DHCP resets to automatic. Providers: Google, Cloudflare (+ Malware / Malware+Adult), OpenDNS, Quad9, AdGuard (ads/trackers, and +malware+adult).

4.8 MicroWin (custom ISO builder)

Invoke-WinUtilISO* functions build a debloated Windows 11 image offline:

  • Mount/verify a Windows 11 ISO; operate on install.wim.
  • Invoke-WinUtilISOScript removes AppX bloatware and OneDrive, optionally injects the running system's drivers into install.wim and boot.wim (index 2), applies offline registry tweaks (hardware-requirement bypass, privacy, OOBE, telemetry, update suppression), and removes CEIP/WU scheduled-task definitions.
  • Optionally writes tools/autounattend.xml to the ISO root for unattended OOBE; embeds setup scripts under C:\Windows\Setup\Scripts\ so they survive Setup stripping unknown-namespace XML.
  • Export to a new ISO or write directly to USB.

Important

MicroWin operates only on the mounted image, never the running OS. It requires substantial free disk space; driver injection significantly increases time and size. Known open issues include product-key verification failures on some debloated images (#4145, #4616).


5. Security Analysis

Area Assessment
Elevation Requires Administrator and self-elevates via Start-Process … -Verb RunAs. By design — every operation is system-level.
Language mode Refuses to run outside FullLanguage mode, which is also the relevant control for AppLocker/Constrained-Language-locked environments.
Remote code execution The standard entry point pipes a remotely fetched script into iex. Trust derives from HTTPS + the official GitHub release. Several tweaks/features also download external EXEs at runtime (Autologon, OOSU10, ViVeTool).
Network egress App installs hit WinGet/Choco sources; specific tweaks/fixes fetch helper tools from sysinternals, oo-software.com, GitHub.
Data handling WinUtil itself transmits no user data. The Sponsors panel scrapes the public GitHub sponsors page.
Destructive operations Remove Edge/OneDrive, AppX removal, SoftwareDistribution deletion, registry deletes, DISM/SFC. Mitigated by Undo scripts and the optional Restore Point tweak.
Error handling Apply primitives wrap operations in typed try/catch and log warnings; a single failed tweak does not abort the batch.
Logging Full session transcript at %LocalAppData%\winutil\logs\winutil_<timestamp>.log.

Warning

For managed/enterprise fleets, treat the irm … | iex pattern as remote code execution. Pin to a vetted winutil.ps1 release, review the embedded config/tweaks.json and config/feature.json InvokeScript bodies, and prefer the -Config exported-profile path over ad-hoc GUI use so changes are reproducible and auditable.

Caution

Disable Updates removes security patching and clears the update cache. Remove Edge/OneDrive and AppX removals are difficult to fully reverse. Always validate on a test machine and keep a restore point.


6. Operations

6.1 Running

Mode Command
Stable GUI irm https://christitus.com/win | iex
Dev GUI irm https://christitus.com/windev | iex
Direct from GitHub irm https://github.com/ChrisTitusTech/winutil/releases/latest/download/winutil.ps1 | iex
Preset, no GUI & ([ScriptBlock]::Create((irm https://christitus.com/win))) -Preset Standard
Config, no GUI & ([ScriptBlock]::Create((irm https://christitus.com/win))) -Config '<file-or-url>' -Noui

6.2 Command-line parameters (scripts/start.ps1)

Parameter Type Effect
-Config <path|url> string Import an exported selection JSON and apply it.
-Preset <Standard|Minimal|Advanced> validated string Apply a built-in preset's tweaks, then exit.
-Noui switch Headless run; requires -Config.
-Offline switch Disable the Install tab and install buttons.

6.3 Unattended deployment

  1. Configure selections in the GUI on a reference machine.
  2. Settings → Export → save winutil.json. WinUtil copies a run command to the clipboard.
  3. Deploy with -Config (+ -Noui for silent). Invoke-WinUtilAutoRun then applies tweaks, features, and installs in order, busy-waiting between phases.

6.4 Config file format

Exported configs are a flat JSON array of selected control keys (apps, tweaks, toggles, features), e.g. ["WPFInstallchrome","WPFTweaksTelemetry","WPFToggleDarkMode"]. Update-WinUtilSelections re-checks the matching boxes; Reset-WPFCheckBoxes restores UI state without retriggering tweak writes (guarded by $sync.ImportInProgress).

6.5 Logs & working files

Path Purpose
%LocalAppData%\winutil\ Working directory (created at startup)
%LocalAppData%\winutil\logs\winutil_<yyyy-MM-dd_HH-mm-ss>.log Start-Transcript session log

6.6 Building from source

# From the repo root, build winutil.ps1 and launch it
.\Compile.ps1 -Run

# Run the latest pre-release build
.\windev.ps1

7. Repository Structure

winutil/
  Compile.ps1                 Build: bundle config+xaml+functions → winutil.ps1
  windev.ps1                  Run latest pre-release build
  sign.bat                    Code-signing helper
  config/                     SOURCE OF TRUTH (JSON)
    applications.json           App catalog (winget/choco IDs, metadata, foss flag)
    tweaks.json                 Tweak definitions (registry/service/appx/scripts)
    feature.json                Config-tab features, fixes, panels
    preset.json                 Standard / Minimal / Advanced
    dns.json                    DNS provider IPv4/IPv6 pairs
    themes.json                 Shared/Light/Dark tokens
    appnavigation.json          Install-tab actions + package-manager radios
  functions/
    private/                    Engine internals (Set-WinUtil*, Invoke-WinUtil*, ISO)
    public/                     UI-facing handlers (Invoke-WPF*)
  scripts/
    start.ps1                   Entry preamble (params, elevation, $sync, logging)
    main.ps1                    GUI bootstrap + event wiring
  xaml/inputXML.xaml           WPF layout + styles
  pester/                      *.Tests.ps1 (config + function tests)
  lint/PSScriptAnalyser.ps1    PSScriptAnalyzer settings
  tools/
    autounattend.xml            MicroWin OOBE answer file
    devdocs-generator.ps1       Generate Hugo docs from JSON
  docs/                        Hugo (hextra theme) documentation site

Note

docs/go.mod/go.sum belong to the documentation website (Hugo + the hextra theme), not to WinUtil itself. The tool has no Go, Node, or compiled dependencies — it runs on in-box PowerShell and WPF.

7.1 Naming conventions

  • WPFInstall<app> — app checkbox (app key from applications.json, prefixed at build time).
  • WPFTweaks<name> — tweak checkbox; WPFToggle<name> — preference toggle.
  • WPFFeature* / WPFFix* / WPFPanel* — Config-tab entries.
  • Invoke-WPF* (public) — UI event handlers; Invoke-WinUtil* / Set-WinUtil* / Get-WinUtil* (private) — engine.

8. Code Quality & Conventions

  • Approved verbs & PSScriptAnalyzer. Functions follow PowerShell verb-noun naming; lint/PSScriptAnalyser.ps1 excludes only PSAvoidUsingWriteHost (Write-Host is used intentionally for console feedback).
  • Comment-based help. Most functions carry .SYNOPSIS/.PARAMETER/.EXAMPLE blocks.
  • PowerShell 5.1 compatibility. Search/filter code deliberately avoids ternaries and advanced syntax, with multi-level $sync fallback, to run on stock Windows PowerShell as well as PowerShell 7.
  • Defensive UI code. High-frequency handlers (e.g. Find-AppsByNameOrDescription, Find-TweaksByNameOrDescription) null-check aggressively and swallow exceptions silently to avoid crashing the WPF thread on every keystroke.
  • Data over code. New apps/tweaks/features are JSON edits; the engine is generic.
  • Testing. pester/configs.Tests.ps1 and pester/functions.Tests.ps1 validate config integrity and function behavior.

9. Potential Improvements

These are observations from the current source, not defects:

  • Invoke-WPFUIElements is monolithic. An inline // TODO notes it should be wrapped in a runspace to render all panels in parallel; it also mixes layout, event wiring, and control creation. Extracting per-control-type builders would aid testability.
  • Initialize-WPFUI partially stubbed. The appscategory branch contains commented-out future work, and default returns "not yet implemented" — indicating an in-progress migration of sidebar generation into this function.
  • Import legacy-format handling is unfinished. Invoke-WPFImpex has a TODO about detecting and flattening the old config JSON shape.
  • Invoke-WPFGetInstalled has a TODO to support Chocolatey as the detection engine (currently winget-centric).
  • Driver/ISO operations are long and serial. MicroWin steps could surface more granular progress and resumability (several open issues relate to mid-build failures).
  • External-download tweaks (ViVeTool, OOSU10, Autologon) fetch from third-party URLs at runtime; pinning/hash-verification would harden them for enterprise use.
  • FAQ/config drift. The shipped FAQ references a "Desktop" preset and a "Clear Tweaks Selection" wording that don't match preset.json (which defines only Standard/Minimal/Advanced) — keep user docs synchronized with the JSON ground truth.

10. Contributing

  • Add an app: add an entry to config/applications.json with category, content, description, link, winget, choco (use na if none), and foss. The build prefixes the key with WPFInstall.
  • Add a tweak: add to config/tweaks.json with Content, Description, category, panel, and any of registry[] / service[] / appx[] / InvokeScript[] / UndoScript[]. Provide OriginalValue/OriginalType (or UndoScript) so it can be reverted.
  • Add a feature/fix: add to config/feature.json; either point function at a public function or supply InvokeScript[]. Map buttons in Invoke-WPFButton.ps1 if not function-driven.
  • Regenerate docs: tools/devdocs-generator.ps1 emits Hugo pages from tweaks.json/feature.json.
  • Test & lint: run the Pester suites in pester/ and PSScriptAnalyzer with lint/PSScriptAnalyser.ps1 before submitting.

See the CONTRIBUTING guide.


11. Quick Reference

Engine functions

Function Role
Invoke-WPFUIElements Render a JSON config into WPF controls
Invoke-WPFButton Dispatch a clicked button to its function/script
Invoke-WinUtilTweaks Apply/undo a tweak (service/registry/script/appx)
Set-WinUtilRegistry Create/set/remove a registry value
Set-WinUtilService Set a service startup type
Set-WinUtilDNS Set adapter DNS from dns.json
Remove-WinUtilAPPX Remove AppX/provisioned packages
Invoke-WPFInstall / Invoke-WPFUnInstall Install/uninstall selected apps
Invoke-WPFRunspace / Invoke-WPFUIThread Background work / UI-thread marshaling
Invoke-WinUtilAutoRun Headless apply (tweaks → features → installs)
Invoke-WinUtilISOScript Apply MicroWin modifications to a mounted WIM

Config files

File Defines
applications.json Installable apps
tweaks.json Tweaks & toggles
feature.json Config-tab features/fixes/panels
preset.json Standard / Minimal / Advanced
dns.json DNS providers
themes.json Theme tokens
appnavigation.json Install-tab actions
Item Value
Working dir %LocalAppData%\winutil\
Logs %LocalAppData%\winutil\logs\winutil_<timestamp>.log
Build script Compile.ps1 (-Run to build + launch)
Source https://github.com/ChrisTitusTech/winutil
Docs https://winutil.christitus.com/