Intune + Winget: Win32 Deployments & Templates¶
Estimated Time: 20–40 min Skill: Intermediate Goal: Deploy apps via Winget + Intune using reusable scripts & Win32 packaging
This guide provides a practical, copy-paste ready template for deploying Win32 apps with Winget via Microsoft Intune.
Use the scripts below as templates — search for the package Id via winget search, replace PACKAGE_ID, then package with the Microsoft Win32 Content Prep Tool.
Jump links¶
Overview • Methods • Scripts (template) • Packaging & Intune settings • Detection & Error Handling • Trusted Sources & Why Winget • Example: Find PACKAGE_ID • Winget-AutoUpdate • Script Signing • TL;DR • Ready-to-copy commands
Overview¶
Winget (Windows Package Manager) lets you install and manage apps via a package ID from a trusted repository. When combined with Intune Win32 deployments, you get a powerful, scriptable way to deliver applications at scale.
Use cases: - One-off app installs
- Repeatable installs across device groups
- Automated updates when paired with Winget-AutoUpdate
Methods¶
1) Deploy Winget (App Installer) as a system app¶
Use the Microsoft Store (New) app type in Intune to install App Installer / DesktopAppInstaller (Winget) as a system app so it exists in C:\Program Files\WindowsApps\... and is available to run in system context.
Intune path: Apps → Add → Windows → Microsoft Store (new) → search App Installer
Why system context?
Winget needs to run without a logged-in user for silent installs at scale.
Deploying App Installer via the Store ensures DesktopAppInstaller is present and accessible to system-level processes.
2) Use Win32 + PowerShell wrapper scripts (recommended)¶
Workflow: 1. Create PowerShell scripts: install_<pkg>.ps1, uninstall_<pkg>.ps1, detection_<pkg>.ps1 (see templates below).
2. Package them into .intunewin with Microsoft Win32 Content Prep Tool.
3. Upload to Intune as Windows app (Win32) and set install/uninstall commands + detection.
Scripts (template)¶
Replace
PACKAGE_IDwith the ID you get fromwinget search <query>(e.g.,7zip.7ziporGitHub.cli).
Template: detection script¶
detection.PACKAGE_ID.ps1
# detection.PACKAGE_ID.ps1
# Exits 0 if package is present, 1 otherwise
param(
[string]$PackageId = 'PACKAGE_ID'
)
# Resolve winget path (App Installer location)
$ResolveWingetPath = Resolve-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe" -ErrorAction SilentlyContinue
if ($ResolveWingetPath) {
$WingetPath = $ResolveWingetPath[-1].Path
$Winget = Join-Path $WingetPath 'winget.exe'
} else {
# Fallback to PATH
$Winget = 'winget'
}
try {
$output = & $Winget list --id $PackageId 2>$null
if ($output -match $PackageId) {
Write-Host "Found $PackageId"
exit 0
} else {
Write-Host "Not Found: $PackageId"
exit 1
}
} catch {
Write-Host "Error running winget: $_"
exit 1
}
Template: install script¶
install.PACKAGE_ID.ps1
# install.PACKAGE_ID.ps1
param(
[string]$PackageId = 'PACKAGE_ID'
)
$ResolveWingetPath = Resolve-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe" -ErrorAction SilentlyContinue
if ($ResolveWingetPath) {
$WingetPath = $ResolveWingetPath[-1].Path
$Winget = Join-Path $WingetPath 'winget.exe'
} else {
$Winget = 'winget'
}
try {
# Example flags for unattended install:
# --silent, --force, --accept-package-agreements, --accept-source-agreements, --exact
& $Winget install --id $PackageId --silent --force --accept-package-agreements --accept-source-agreements --exact | Out-Null
Write-Host "Install command exited with code $LASTEXITCODE"
exit $LASTEXITCODE
} catch {
Write-Error "Install failed: $_"
exit 1
}
Template: uninstall script¶
uninstall.PACKAGE_ID.ps1
# uninstall.PACKAGE_ID.ps1
param(
[string]$PackageId = 'PACKAGE_ID'
)
$ResolveWingetPath = Resolve-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe" -ErrorAction SilentlyContinue
if ($ResolveWingetPath) {
$WingetPath = $ResolveWingetPath[-1].Path
$Winget = Join-Path $WingetPath 'winget.exe'
} else {
$Winget = 'winget'
}
try {
& $Winget uninstall --id $PackageId --silent --force --accept-source-agreements | Out-Null
Write-Host "Uninstall command exited with code $LASTEXITCODE"
exit $LASTEXITCODE
} catch {
Write-Error "Uninstall failed: $_"
exit 1
}
Packaging & Intune settings¶
Prepare .intunewin¶
Use Microsoft Win32 Content Prep Tool:
IntuneWinAppUtil.exe -c "C:\Path\To\PackageFolder" -s "install.PACKAGE_ID.ps1" -o "C:\Output"
PackageFolder contains your 3 scripts and any helpers.- The tool creates
yourpackage.intunewin for upload. Intune App configuration (in Admin Center)¶
- App type: Windows app (Win32)
Install command
powershell.exe -ExecutionPolicy Bypass -File .\install.PACKAGE_ID.ps1
Uninstall command
powershell.exe -ExecutionPolicy Bypass -File .\uninstall.PACKAGE_ID.ps1
Detection rule - Type: Use a custom detection script → upload detection.PACKAGE_ID.ps1
- Run script as 32-bit process on 64-bit clients: No (unless required)
- Enforce script signature check and run script silently: optional — recommended for production (see signing section)
Requirements: Windows 10/11, architecture x64, minimum build number, etc.
Assignment: target device groups; start with a pilot group.
Detection & Error Handling¶
Detection rules
Reliable detection prevents repeated reinstalls. You can:
- Use the PowerShell script above (exit codes: 0 OK, non-zero fail)
- or use registry-based detection (when known keys exist)
- or file existence checks for specific executable paths
Error handling / logging¶
Write logs to C:\ProgramData\IntuneLogs\:
$LogPath = "C:\ProgramData\IntuneLogs\winget_install.log"
"[$(Get-Date)] Installing $PackageId" | Out-File -FilePath $LogPath -Append
# on error:
"[$(Get-Date)] Error: $_" | Out-File -FilePath $LogPath -Append
Trusted Sources & Why Winget¶
Why source trust matters
Winget uses sources (Microsoft Community Repository, private repos). Packages must be from trusted sources because:
- Signed packages reduce supply-chain risk.
- Source validation prevents man-in-the-middle attacks or malicious packages.
- Intune + Winget together allow central governance over which sources devices can access.
Winget advantages¶
- Modern package management — similar to apt/choco/homebrew.
- Lightweight — no need to host large MSI/EXE assets.
- Versioning & updates — easier to maintain and automate.
- Scriptable — integrates cleanly with PowerShell and automation tooling.
How to verify sources¶
winget source list
- Enforce source agreements where required.
Example: How to find the PACKAGE_ID¶
Search:
winget search github.cli
Example output:
Name Id Version Source
----------------------------------------------
GitHub CLI GitHub.cli 2.81.0 winget
PACKAGE_ID for your scripts (e.g., GitHub.cli). Winget-AutoUpdate (optional)¶
Integrate WAU to keep packages patched:
- Deploy WAU as a scheduled task / service via Intune.
- Control update frequency and whitelist/blacklist packages.
- WAU can run in system context and call
winget upgrade --allwith filters.
Repo: https://github.com/Romanitho/Winget-AutoUpdate
Script Signing & Enforcement (recommended for prod)¶
If your org enforces script signature checks: - Sign your PowerShell scripts with a code-signing certificate trusted by endpoints.
- In Intune, set Enforce script signature check and run script silently to Yes when uploading detection scripts.
- If you do not have a corporate CA, rotate to a private PKI or use Azure Key Vault + certificate provisioning.
Basic signing (dev/test):
Set-AuthenticodeSignature -FilePath .\install.PACKAGE_ID.ps1 -Certificate (Get-ChildItem Cert:\CurrentUser\My\THUMBPRINT)
TL;DR¶
1) Use winget for lightweight installs.
2) Wrap installs/uninstalls in PowerShell scripts.
3) Package into .intunewin and upload to Intune.
4) Use detection scripts to validate installs.
5) Prefer trusted/managed winget sources; sign scripts for production.
Template usage: run
winget search <app>→ replacePACKAGE_IDin the three scripts → package & deploy via Intune.
Ready-to-copy filenames & Intune commands¶
Files (examples)
install.PACKAGE_ID.ps1
uninstall.PACKAGE_ID.ps1
detection.PACKAGE_ID.ps1
Intune Install command
powershell.exe -ExecutionPolicy Bypass -File .\install.PACKAGE_ID.ps1
Intune Uninstall command
powershell.exe -ExecutionPolicy Bypass -File .\uninstall.PACKAGE_ID.ps1
Detection - Use custom detection script (detection.PACKAGE_ID.ps1)
- Do not run as 32-bit process on 64-bit clients (unless required)
- Consider enforcing script signature checks in production
Join the Discussion
Got a question, idea, or a better way to do it? Drop it below — I read every comment and update guides based on real-world feedback.
FeedbackAdd something useful. Ask good questions. Help someone else learn.