A PowerShell-based, automated provisioning solution that transforms Windows 10 & 11 workstation deployment from a 30-step manual process into a single "plug-and-play" operation. Whether you're imaging bare metal, cleaning up an existing PC, or running routine maintenance on already-deployed machines, DeployWorkstation handles bloatware removal, essential application installation, and in-place app upgrades.
| # | File | Issue | Fix |
|---|---|---|---|
| 1 | DeployWorkstation.ps1 |
Microsoft.DotNet.Framework.4.8 was never a valid winget package ID, so every run failed that install with 0x8A150014 NO_APPLICATIONS_FOUND. |
Corrected to Microsoft.DotNet.Framework.Runtime (currently 4.8.1), with Microsoft.DotNet.Framework.DeveloperPack_4 as a fallback ID. On Win10 1903+ / Win11 the runtime ships in-box, so this typically resolves to a fast no-op. |
| 2 | DeployWorkstation.ps1 |
Reboot exit codes 0x8A150109 (restart to finish) and 0x8A15010A (restart before install) were misclassified as network errors; successful installs that only needed a reboot (Adobe Reader does this regularly) were retried twice, then logged as network failures. |
Reboot-to-finish now counts as success, sets a RebootNeeded flag, and a restart notice is shown in the summary and at end of run. Reboot-before-install fails with the correct reason. |
| 3 | DeployWorkstation.ps1 |
Several exit-code hex comments were wrong (-1978335212 labeled 0x8A15002C is actually 0x8A150014; -1978334960 labeled "blocked by policy" is actually a dependency failure). |
Exit-code tables rebuilt against the official winget returnCodes.md; unknown codes now log their hex form for easy lookup. |
| 4 | DeployWorkstation.ps1 |
winget install/upgrade ran without --exact, so a substring ID match could hit the wrong package or fail as ambiguous. |
Added --exact (plus --disable-interactivity to prevent hangs on prompts) to all winget install/upgrade calls. |
| 5 | DeployWorkstation.ps1 |
In update mode, apps not installed on the machine were counted as update failures. | 0x8A150014 from winget upgrade --id is now logged as SKIPPED (not installed) and tracked separately in the summary. |
Winget package IDs get renamed and retired over time. v5.3 verifies every ID against the winget source before installing, and recovers automatically when one has changed:
- Primary ID โ checked with
winget show --exact - Fallback IDs โ an optional per-app list of known alternates, tried in order
winget searchby display name โ adopted automatically only if the result is unambiguous; otherwise candidate IDs are logged so you can update the app list
Results are cached per run (install + update share the cache), adding only a few seconds to a full deployment.
Other reliability improvements: --include-unknown on upgrades (handles apps whose installed version winget can't read โ common after Windows Update services .NET runtimes out from under winget), and installer hash-mismatch errors now trigger a winget source update before retrying, since they're usually caused by a stale manifest.
๐ Bugs Fixed in v5.2
| # | File | Issue | Fix |
|---|---|---|---|
| 1 | QuickStart.cmd |
All 4 menu options passed -ConfigFile โ a parameter that doesn't exist in the PS1. Every choice errored immediately. |
Rewrote to use the actual -SkipBloatwareRemoval, -SkipAppInstall, -SkipSystemConfig, and -UpdateApps params. |
| 2 | QuickStart.cmd |
goto start on invalid input โ no :start label existed โ cmd.exe crashed the script. |
Added :start label at the top of the menu block. |
| 3 | tests/DeployWorkstation.Tests.ps1:42 |
Test asserted DeployWorkstation.cmd exists โ it never did โ permanent CI failure. |
Changed to check QuickStart.cmd which actually exists. |
| 4 | .github/workflows/test-powershell.yml:37 |
upload-artifact@v3 was deprecated and removed by GitHub. |
Upgraded to @v4. |
| 5 | DeployWorkstation.ps1:587 |
winget --version can output multiple lines; -replace on an array returns an array; [Version] cast on an array throws and silently skips the minimum version check. |
Added Where-Object + Select-Object -Last 1 before the replace. |
| # | File | Issue | Fix |
|---|---|---|---|
| 6 | DeployWorkstation.ps1:529 |
Set-ExecutionPolicy was placed mid-file after all function definitions โ if it threw, the machine would be left partially configured. |
Moved to line 26, right after $ProgressPreference. |
| 7 | DeployWorkstation.ps1:535 |
$script:IsWin11 computed but never referenced anywhere. |
Removed. |
| 8 | Export-HtmlReport |
Called Get-CimInstance Win32_OperatingSystem a second time at report generation, even though it was already cached as $script:OsInfo. |
Replaced with $script:OsInfo. |
- ๐ Self-Elevating & Policy-Bypassing โ Automatically relaunches under Windows PowerShell 5.1 with
-ExecutionPolicy Bypassand UAC elevation - ๐๏ธ UWP "Bloatware" Purge โ Comprehensive removal of built-in apps including Copilot, Teams, New Outlook, Clipchamp, OneDrive, Xbox, and more
- โ๏ธ Win32/MSI Removal & DISM Cleanup โ Enterprise software removal via WinGet, DISM, and registry manipulation
- ๐ฆ Standard App Installation & Upgrade โ Automated install and in-place upgrade of essential third-party tools via WinGet
- ๐ Package ID Auto-Resolution (new in 5.3) โ Verifies every winget ID before install; recovers from renamed/retired IDs via per-app fallbacks and
winget search, and logs replacement candidates - ๐ Reboot-Aware Exit Handling (new in 5.3) โ Installs that succeed but require a restart are counted as success, flagged in the summary, and surfaced with a restart notice at end of run
- ๐ Centralized Logging โ Detailed operation logs plus a dark-themed HTML report with system info summary and full event log
- ๐ App Update Support โ Detects and upgrades already-installed applications in-place; safe to re-run on existing machines
- ๐ก๏ธ Winget Auto-Bootstrap โ Automatically downloads and installs winget on OEM machines where it's missing or outdated (v5.3 requires winget 1.4+ and bootstraps it automatically)
- ๐ Smart Retry Logic โ Automatic retries with delay on genuinely transient errors (network faults, stale-manifest hash mismatches); reboot and policy errors are correctly identified instead of blindly retried
- ๐ฅ๏ธ Windows Edition Awareness โ Detects Home vs. Pro/Enterprise and warns when policy keys will have no effect
- ๐๏ธ OEM OneDrive Removal โ Three-path removal covering both Appx and embedded OEM binaries
- ๐ Multi-Language Support โ Auto-detects locale via
Get-Culture; ships withen-USandes-ES - โ
Real-time Progress โ
Write-Progressconsole bars throughout all major operations
- ๐ง New Outlook (Microsoft.OutlookForWindows)
- ๐ค Copilot Assistant
- ๐ฅ Microsoft Teams (Consumer)
- ๐ฌ Clipchamp Video Editor
- ๐จโ๐ฉโ๐งโ๐ฆ Family Safety & Parental Controls
- โ๏ธ OneDrive Sync Client (Appx + OEM binary)
- ๐ผ LinkedIn Integration
- ๐ Skype for Windows
- ๐ฎ Xbox Gaming Suite
- ๐ฅฝ Mixed Reality Portal
- ๐ฅ๏ธ Remote Desktop App
- ๐ Quick Assist
- ๐ Quick Assist capability
- ๐ฎ Xbox TCUI, Game Overlay & Speech-to-Text overlays
- ๐ OpenSSH Client
- ๐ก๏ธ McAfee Security Suite (registry-based uninstall)
- Disables Windows telemetry collection
- Disables Windows Error Reporting
- Disables CEIP (Customer Experience Improvement Program)
- Disables Advertising ID
- ๐ฆ Malwarebytes โ Malware protection
- ๐งน BleachBit โ System cleanup and privacy tool
- ๐ Google Chrome โ Web browser
- ๐๏ธ 7-Zip โ Universal archive manager
- ๐ Adobe Acrobat Reader DC (64-bit) โ PDF viewer
- ๐น VLC Media Player โ Universal media player
- โ๏ธ .NET Framework Runtime (4.8.1) โ Legacy app compatibility; ships in-box on Win10 1903+/Win11, so this is usually a no-op
- โ๏ธ .NET 8 Desktop Runtime โ LTS, supported through November 2026
- โ๏ธ .NET 10 Desktop Runtime โ LTS, supported through November 2030
- ๐ง Visual C++ 2015โ2022 Redistributables (x64 & x86)
- ๐ป Windows 10/11 (Most Editions)
- ๐ Internet Connection (for WinGet packages โ Winget 1.4+ auto-installs if missing or outdated)
- ๐ค Administrator Access
- ๐พ USB Drive or Network Share (Optional)
-
๐ฅ Download the Repository
git clone https://github.com/Pnwcomputers/DeployWorkstation.git cd DeployWorkstation -
๐พ Prepare Deployment Media
copy DeployWorkstation.ps1 E:\ copy DeployWorkstation.bat E:\
-
โถ๏ธ Execute Deployment:: Method 1: Double-click the .bat launcher (recommended) DeployWorkstation.bat :: Method 2: Direct PowerShell execution powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\DeployWorkstation.ps1
-
โณ Select Deployment Mode
The launcher presents six options:
Option Description 1 - Full Deployment Bloatware removal + app install + system config 2 - Bloatware Removal Only Skips app installation and system config 3 - App Installation Only Skips bloatware removal and system config 4 - System Config Only Registry/policy hardening only 5 - Update Installed Apps Upgrades managed apps in-place 6 - Exit -
โ Review & Reboot
- Script pauses for final review on completion
- HTML report generated:
DeployWorkstation.html - Detailed log available:
DeployWorkstation.log - If any install requires a restart to finish, the summary and end-of-run output say so explicitly
- System reboot recommended for a clean finish
v5.3 is safe to run on already-deployed workstations. The upgrade logic updates any managed apps with newer versions available via winget, skips apps that aren't installed on the machine, and picks up apps whose installed version winget can't read (--include-unknown).
# Update managed apps only
.\DeployWorkstation.ps1 -SkipBloatwareRemoval -SkipSystemConfig -UpdateApps
# Re-run app install on a previously cleaned machine
.\DeployWorkstation.ps1 -SkipBloatwareRemoval| Parameter | Description |
|---|---|
-SkipAppInstall |
Skip all application installation |
-SkipBloatwareRemoval |
Skip bloatware and UWP removal |
-SkipSystemConfig |
Skip registry/policy hardening |
-UpdateApps |
Upgrade already-installed managed apps in-place |
-LogPath <path> |
Custom path for the log file |
-ReportPath <path> |
Custom path for the HTML report |
To add or change which apps are installed, edit the $script:ManagedApps array near the top of DeployWorkstation.ps1. Each entry needs a winget ID and a display name; an optional Fallbacks list holds alternate IDs to try if the primary one is ever renamed or retired:
$script:ManagedApps = @(
@{ Id = 'Google.Chrome'; Name = 'Google Chrome'
Fallbacks = @('Google.Chrome.EXE') },
@{ Id = 'Notepad++.Notepad++'; Name = 'Notepad++' },
# add more entries here
)The Name field doubles as the winget search term of last resort, so keep it close to the app's actual display name in the winget catalog.
Find winget IDs with: winget search <AppName>
| Profile | Use Case | Applications | Configuration |
|---|---|---|---|
| Corporate | Business workstations | Office tools, security software | Details |
| Developer | Programming workstations | IDEs, development tools | Details |
| Home User | Personal computers | Media, communication apps | Details |
| Feature | Manual Deployment | Other Tools | DeployWorkstation |
|---|---|---|---|
| Automation Level | โ Manual (8+ hours) | โ Full Automation (30 minutes) | |
| Bloatware Removal | โ Manual deletion | โ Comprehensive purge | |
| Enterprise Software | โ Manual uninstall | โ Often skipped | โ Registry-based removal |
| App Updates | โ Manual per-app | โ In-place upgrade on re-run | |
| Package ID Drift | โ Silent failures | โ Silent failures | โ Auto-resolution + logged candidates |
| Error Handling | โ Manual intervention | โ Smart retry logic + HTML report | |
| Multi-Language | โ | โ | โ en-US & es-ES auto-detected |
| Metric | Traditional Method | DeployWorkstation |
|---|---|---|
| Total Time | 4-8 hours | 30-45 minutes |
| Manual Steps | 30+ operations | 1 double-click |
| Error Rate | ~15% (human error) | <2% (automated) |
| Consistency | Variable | 100% standardized |
- New employee workstation setup
- Hardware refresh projects
- Standardized corporate imaging
- Remote office provisioning
- Client workstation deployment and routine maintenance
- Malware cleanup and rebuild
- Hardware upgrade services
- Maintenance contract fulfillment โ re-run to keep apps current
- Lab computer preparation
- Student workstation imaging
- Faculty equipment setup
- Semester refresh operations
- Personal computer setup
- Family PC maintenance
- Small office standardization
Script won't execute
- Ensure PowerShell execution policy allows scripts
- Verify UAC elevation is working
- Check Windows PowerShell 5.1 is available
WinGet installation failures
- The script will attempt to auto-install/repair winget on OEM machines (v5.3 requires winget 1.4+ and bootstraps the current release automatically)
- Verify internet connectivity if bootstrap also fails
- Update Windows to latest version
Bloatware returns after reboot
- Run script as Administrator
- Ensure all user profiles are processed
- Check Group Policy restrictions
App install fails with "Package ID not found in winget source"
- v5.3 tries fallback IDs and a
winget searchautomatically before reporting this - Check the log for a "Possible replacement IDs" line; it lists candidates when the search was ambiguous
- Verify the current ID manually (
winget search <AppName>), then update theId(or add aFallbacksentry) in$script:ManagedApps - Run
winget source updateto refresh the package index
Install marked OK but says "restart required to finish"
- This is success, not an error โ some installers (Adobe Reader in particular) finish on the next boot
- Reboot the machine; re-running the script afterward will confirm the app as already installed
# Check for errors and warnings in the deployment log
Get-Content .\DeployWorkstation.log | Select-String "ERROR|WARN"
# Verify WinGet package status
winget list --source wingetThe HTML report (DeployWorkstation.html) provides the same information in a readable format โ open it in any browser after the run completes.
DeployWorkstation/
โโโ DeployWorkstation.ps1 # Main PowerShell script
โโโ DeployWorkstation.bat # Self-elevating launcher with full menu
โโโ QuickStart.cmd # Simplified quick-launch menu
โโโ Installers/ # Place offline installers here (optional)
โโโ Logs/ # Auto-created; holds log and HTML report
โ โโโ DeployWorkstation.log
โ โโโ DeployWorkstation.html # Post-run HTML report
โโโ Config/
โ โโโ Examples/
โ โโโ Corporate.json # Example corporate profile
โ โโโ Developer.json # Example developer profile
โ โโโ HomeUser.json # Example home user profile
โโโ docs/
โ โโโ CONFIGURATION.md
โ โโโ INSTALLATION.md
โ โโโ TROUBLESHOOTING.md
โ โโโ FAQ.md
โ โโโ COMPATABILITY.md
โโโ tests/
โโโ DeployWorkstation.Tests.ps1
- ๐ฅ๏ธ GUI Configuration Interface (pre-run checkbox dialog)
- ๐ Web-based Management Console
- ๐ Domain Integration
- ๐ Cloud Configuration Sync
- ๐ Windows Server Hardening Mode (no app install)
- ๐ Analytics & Telemetry (CSV/JSON export for fleet tracking)
We welcome contributions! Here's how to get started:
- ๐ Documentation โ Improve README clarity, add configuration examples, create troubleshooting guides
- ๐ Bug Reports โ Open issues with detailed descriptions, system info, and log excerpts
- ๐ก Feature Requests โ Open issues with
[FEATURE]tag, describe use case and benefits - ๐ Security Issues โ Email support@pnwcomputers.com with proof of concept; allow reasonable disclosure time
This project is licensed under the MIT License โ See the LICENSE file for details.
- ๐ Documentation: Check this README and the project wiki
- ๐ Bug Reports: Open an issue on GitHub
- ๐ก Feature Requests: Open an issue with
[FEATURE]tag - ๐ฌ General Support: support@pnwcomputers.com
๐ฏ Transform your Windows deployment process from hours to minutes, and keep it current with every re-run.
Built with โค๏ธ for efficiency, reliability, and zero-touch automation.
โญ Star this repo if it saved you time and effort!
Updated August 2026 Tested on Windows 10 (1909+) and Windows 11 โ Pro & Home Editions
