WinGet Guides

Schedule Auto-Updates for All Apps with WinGet + Task Scheduler

Windows Package Manager (WinGet) is Microsoft’s fast, safe, and scriptable package manager for Windows 10/11. It lets you install, upgrade, and manage apps from trusted sources with a single command. For IT pros and power users, WinGet becomes especially valuable when you schedule it to automatically update all applications on a regular cadence. That’s exactly what this guide helps you achieve.

This is a practical, comprehensive tutorial packed with ready-to-use commands, copy/paste PowerShell, optional YAML configuration, and multiple ways to automate updates via Task Scheduler. By the end, you’ll have reliable, silent, fully unattended updates for your Windows apps using WinGet.

Contents show

Overview of the Use Case

In plain language, this guide shows you how to configure your PC (or a fleet of PCs) to automatically run WinGet to upgrade all installed apps on a schedule. That means Windows will regularly check for newer versions of your software and install them quietly—without user interaction—so your system stays secure and up-to-date.

Common scenarios where this is useful:

  • Fresh installs and rebuilds: After imaging a PC, schedule automatic updates to keep the baseline hardened and current.
  • Bulk updates across a lab or small fleet: Use one script and a Scheduled Task to keep every station in sync.
  • CI/CD automation and dev workstations: Keep developer tools current without manual overhead.
  • Remote/hybrid workforce: Reduce helpdesk tickets by keeping apps consistently updated.
  • Kiosk/shared devices: Maintain security posture without exposing manual update prompts.

Quick Reference Table

Command Purpose Example Output
winget –info Show WinGet version, sources, and system info Windows Package Manager v1.6.x…; Sources: winget, msstore
winget list –upgrade-available List apps with available updates Name Version Available Source Id…
winget upgrade –all –silent –accept-source-agreements –accept-package-agreements Silently upgrade all updatable apps Found 7 upgrades. Upgrading: 1/7 PowerToys… Done
winget upgrade –id –exact –silent Upgrade a specific app silently Upgrading Notepad++.Notepad++… Successful
winget source list Show configured sources Name: winget, Type: Microsoft.Rest…
winget source update Refresh source indexes Done
winget source reset –force Rebuild sources (fixes index errors) Resetting sources… Done
winget export -o packages.json Export installed apps Exported 85 packages to packages.json
winget import -i packages.json –silent –accept-* Import and install from list Installing 85 packages… Done
schtasks /Create … Create a Scheduled Task from cmd SUCCESS: The scheduled task “WinGet-AutoUpdate” has successfully been created.
Register-ScheduledTask … Create a Scheduled Task from PowerShell TaskPath TaskName State

Key Concepts and Prerequisites

  • Tools you need:

    • Windows 10 (1909+) or Windows 11
    • WinGet (Windows Package Manager), included with the Microsoft App Installer
    • PowerShell 5.1 (built-in) or PowerShell 7.x (optional)
    • Task Scheduler (built-in)
    • Administrative rights are recommended for machine-wide updates
  • How to check if WinGet is installed and its version:

    • Command: winget –info
    • If WinGet is missing, install/update “App Installer” from Microsoft Store (Publisher: Microsoft Corporation).
  • Understanding sources:

    • The default source is winget (community manifests).
    • Optional sources include msstore (Microsoft Store).
    • Use winget source list and winget source update to inspect and refresh sources.
  • Silent and unattended operation:

    • Use these flags for automation: –silent, –disable-interactivity, –accept-source-agreements, –accept-package-agreements.
    • Some packages may still require elevation. Use Scheduled Task with “Run with highest privileges.”
  • Logging:

    • WinGet logs: %LOCALAPPDATA%\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\DiagOutputDir
    • Best practice: also create your own log file for the scheduled run.
See also  WinGet in CI/CD: Provision Windows Build Agents the Right Way

Step-by-Step Guide

1) Verify and prepare WinGet

  1. Open Windows Terminal or PowerShell as Administrator.

  2. Check version and sources:

    winget –info
    winget source list
    winget source update

  3. Optional: Export your current app list (handy for rebuilds):

    winget export -o C:\Temp\packages.json

2) Test a manual upgrade run

Run a one-time upgrade to confirm WinGet is healthy and apps update silently:

winget upgrade –all –include-unknown –silent –disable-interactivity –accept-source-agreements –accept-package-agreements

  • Add –include-unknown to attempt upgrades even when versions aren’t fully known to WinGet.
  • If you see UAC prompts, you’ll handle that by running your task “with highest privileges.”

3) Create a robust PowerShell updater script

Save the following script as C:\ProgramData\WinGet\Update-AllApps.ps1. It updates sources, upgrades all apps silently, writes logs, and returns an appropriate exit code for monitoring.

C:\ProgramData\WinGet\Update-AllApps.ps1

Purpose: Silently update all WinGet apps and log results.

param(
[switch]$IncludeUnknown = $true,
[string]$LogFolder = “C:\ProgramData\WinGet\Logs”
)

Ensure log folder

if (-not (Test-Path $LogFolder)) {
New-Item -ItemType Directory -Path $LogFolder -Force | Out-Null
}

$timeStamp = Get-Date -Format “yyyyMMdd-HHmmss”
$logFile = Join-Path $LogFolder “WinGet-Upgrade-$timeStamp.log”

Helper to run a command and tee to log

function Invoke-Logged {
param([string]$CommandLine)
n=== $CommandLine ===n” | Tee-Object -FilePath $logFile -Append
cmd.exe /c $CommandLine 2>&1 | Tee-Object -FilePath $logFile -Append
return $LASTEXITCODE
}

Update sources first

$code1 = Invoke-Logged “winget source update”

Build upgrade command

$upgradeArgs = @(“upgrade”,”–all”,”–silent”,”–disable-interactivity”,”–accept-source-agreements”,”–accept-package-agreements”)
if ($IncludeUnknown) { $upgradeArgs += “–include-unknown” }

$cmd = “winget ” + ($upgradeArgs -join ” “)
$code2 = Invoke-Logged $cmd

Show a short summary in the log

nCompleted at $(Get-Date). Exit codes: source=$code1 upgrade=$code2n” | Tee-Object -FilePath $logFile -Append

Exit with the most significant non-zero code (if any)

if ($code2 -ne 0) { exit $code2 }
exit $code1

Notes:

  • The script purposely uses cmd.exe /c inside PowerShell to capture Winget console output reliably into the log.
  • Logs are written to C:\ProgramData\WinGet\Logs. Consider centralizing with a SIEM or log shipping if needed.

Test it once interactively:

PowerShell -ExecutionPolicy Bypass -File “C:\ProgramData\WinGet\Update-AllApps.ps1”

4) Create a Scheduled Task (GUI method)

  1. Open Task Scheduler
  2. Create Task…
  3. General:
    • Name: WinGet Auto-Update
    • Description: Silently upgrades all apps via WinGet.
    • Select: Run whether user is logged on or not
    • Check: Run with highest privileges
    • Configure for: Your Windows version
    • Security options: Choose the user that will run the task (prefer the logged-in admin or service account that has WinGet available). For reliability, run as the target user context rather than SYSTEM.
  4. Triggers:
    • New… Daily at a time outside active work hours
    • Optional: Delay task for up to: 30 minutes (randomizes start)
    • Optional: Repeat task every: 1 day (or weekly)
  5. Actions:
    • New… Start a program
    • Program/script: powershell.exe
    • Add arguments:
      -NoProfile -ExecutionPolicy Bypass -File “C:\ProgramData\WinGet\Update-AllApps.ps1”
  6. Conditions:
    • Start the task only if the computer is on AC power (recommended for laptops)
    • Wake the computer to run this task (optional)
  7. Settings:
    • Allow task to be run on demand
    • Stop the task if it runs longer than: 2 hours (adjust as needed)
    • If the task fails, restart every 30 minutes, attempt 3 times

Click OK and provide credentials when prompted. Test the task with “Run” to ensure it works headless.

5) Create a Scheduled Task (command line: schtasks)

Run from an elevated cmd:

schtasks /Create /TN “WinGet-AutoUpdate” /RU “<DOMAIN\Username>” /RP “” ^
/TR “powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\ProgramData\WinGet\Update-AllApps.ps1” ^
/SC DAILY /ST 03:00 /RL HIGHEST /F

  • Replace <DOMAIN\Username> and as appropriate.
  • For local accounts use MACHINE\Username or just Username.
  • Add /AC if you want to restrict to AC power via Conditions (GUI-only option); otherwise, handle via policy.
See also  Handling Winget Install Conflicts and Silent Switches Like a Pro

6) Create a Scheduled Task (PowerShell: Register-ScheduledTask)

$Action = New-ScheduledTaskAction -Execute “powershell.exe” -Argument ‘-NoProfile -ExecutionPolicy Bypass -File “C:\ProgramData\WinGet\Update-AllApps.ps1″‘
$Trigger = New-ScheduledTaskTrigger -Daily -At 3:00AM
$Principal = New-ScheduledTaskPrincipal -UserId “$env:USERDOMAIN\$env:USERNAME” -LogonType Password -RunLevel Highest
$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries:$false -DontStopIfGoingOnBatteries:$false -StartWhenAvailable

Prompts for password; supply a secure string if automating

Register-ScheduledTask -TaskName “WinGet-AutoUpdate” -Action $Action -Trigger $Trigger -Principal $Principal -Settings $Settings

Optional tweaks:

  • Add a random delay:

    $Trigger.RandomDelay = [TimeSpan]”0:30:00″

  • Run Weekly:

    $Trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Sunday -At 3:00AM

7) Optional: Custom YAML config to control exclusions, pins, and logging

If you want extra control (exclude certain apps, pin versions, adjust logging), you can drive the script with a simple YAML file and extend the script to read it. Save as C:\ProgramData\WinGet\AutoUpdate.yaml:

C:\ProgramData\WinGet\AutoUpdate.yaml

Purpose: Optional configuration consumed by your PowerShell script.

NOTE: This is a custom YAML for the script below, not a WinGet manifest.

logging:
folder: “C:\ProgramData\WinGet\Logs”

upgrade:
includeUnknown: true # include –include-unknown
excludeIds: # do not update these packages

  • “Nvidia.GeForceExperience”
  • “Oracle.JavaRuntimeEnvironment”
    pins: # pseudo-pins for the script (for real ‘winget pin’, see Best Practices)
  • id: “Git.Git”
    version: “2.46.0” # keep at this version; do not auto-update
  • id: “Python.Python.3.11”
    version: “3.11.9”

schedule:
time: “03:00” # not used by Task Scheduler directly; for documentation only

Extend the script to read YAML (requires PowerShell’s YAML module):

Install-Yaml support once on the system (requires internet)

Install-Module -Name powershell-yaml -Scope AllUsers -Force

Import-Module powershell-yaml

$configPath = “C:\ProgramData\WinGet\AutoUpdate.yaml”
if (Test-Path $configPath) {
$conf = (Get-Content $configPath -Raw) | ConvertFrom-Yaml
if ($conf.logging.folder) { $LogFolder = $conf.logging.folder }
$IncludeUnknown = [bool]$conf.upgrade.includeUnknown
$ExcludeIds = @($conf.upgrade.excludeIds)
$Pins = @($conf.upgrade.pins)

# Example: Convert pins to real 'winget pin' at runtime
foreach ($p in $Pins) {
    if ($p.id -and $p.version) {
        cmd.exe /c "winget pin add --id `"$($p.id)`" --version `"$($p.version)`"" | Out-Null
    }
}

}

This is optional. If you prefer simplicity, stick to the core script shown earlier.

8) Optional: WinGet Configuration (YAML) to declare desired packages

WinGet supports a separate feature called “WinGet Configuration” to declare the desired state of software (ensure Present/Latest). You can store and apply that YAML in your environment builds, then keep updates scheduled as shown above. Minimal example:

Example WinGet Configuration YAML (apply with: winget configure –apply .\config.yaml)

This ensures certain apps are installed; your scheduled task then keeps them updated.

For schema and the latest syntax, consult official docs: aka.ms/winget-config

$schema: https://aka.ms/winget-config.schema.json
properties:
resources:

  • resource: Microsoft.WinGet.DSC/WinGetPackage
    id: NotepadPP
    directives:
    description: Ensure Notepad++ is installed
    settings:
    id: Notepad++.Notepad++
    source: winget
  • resource: Microsoft.WinGet.DSC/WinGetPackage
    id: VisualStudioCode
    settings:
    id: Microsoft.VisualStudioCode
    source: winget

Then schedule either your update script or directly:

winget configure –apply C:\Config\config.yaml

Troubleshooting

Common issues and exact fixes:

  • Problem: Hash mismatch or security hash error

    • Explanation: The downloaded installer no longer matches the manifest hash (publisher updated the binary).

    • Fixes:

      • Refresh sources:

        winget source update

      • Retry upgrade:

        winget upgrade –all –silent –accept-source-agreements –accept-package-agreements

      • If urgent and you trust the source, you can bypass hash verification for a specific install/upgrade:

        winget install –id –silent –ignore-security-hash –accept-package-agreements –accept-source-agreements

        Use sparingly; restore normal verification on the next cycle.

  • Problem: Multiple installers found or ambiguous installer selection

    • Explanation: Package has multiple architectures/scopes/installer types.

    • Fix: Specify filters explicitly:

      winget upgrade –id –exact –silent –architecture x64 –scope machine

      Other useful filters: –locale en-US, –source winget

  • Problem: No applicable update found even when a newer version exists

    • Explanation: Version detection may be unknown for that package.

    • Fix: Include unknown versions and force retry:

      winget upgrade –all –include-unknown –silent –disable-interactivity –accept-source-agreements –accept-package-agreements

  • Problem: Source index or database corruption

    • Symptoms: Errors like “Failed when opening source” or “Aggregate source failure”

    • Fix:

      winget source reset –force
      winget source update

      If issues persist, sign out/in or reinstall “App Installer” from the Microsoft Store.

  • Problem: Winget not found in Scheduled Task when running as SYSTEM

    • Explanation: WinGet (App Installer) is deployed per-user; SYSTEM may not see it.
    • Fix:
      • Run the task under a user context that has WinGet installed (recommended).
      • Or deploy App Installer MSIX for all users and ensure PATH resolution, then test thoroughly.
  • Problem: UAC prompts halt the scheduled run

    • Fix: In the task’s General tab, check “Run with highest privileges.” Also use:

      –silent –disable-interactivity –accept-source-agreements –accept-package-agreements

  • Problem: App-specific installers require manual interaction

    • Fix: Exclude or pin those apps, or research app-specific installer switches. You can exclude with a custom script (see YAML section above) or use:

      winget pin add –id

See also  Private WinGet Source: How to Host Your Own Repository

Automation Tips

  • Combine WinGet with PowerShell for control:

    • Add pre-checks (disk space, battery/AC).
    • Kill known blocking processes before upgrade (optional).
    • Retry failed packages individually.
  • Task Scheduler best practices:

    • Run daily or weekly during off-hours.
    • Randomize start within 15–30 minutes to reduce contention on shared networks.
    • Enable “Run with highest privileges.”
    • Configure stop-after duration and restart-on-failure.
  • Intune/MEM:

    • Wrap the script (Update-AllApps.ps1) into a Win32 app or use the Intune Management Extension as a scheduled script.
    • For devices joined to Azure AD, the user context still matters; test under the same user that has App Installer/WinGet.
  • CI/CD scenarios:

    • In build agents or self-hosted runners on Windows, add a step to:

      winget source update
      winget upgrade –all –silent –accept-source-agreements –accept-package-agreements

    • Cache or mirror installers if you need hermetic builds.

  • Offline or restricted networks:

    • Consider adding a private WinGet REST source:

      winget source add -n Contoso -a https://packages.contoso.local/api

    • Mirror required installers internally and curate manifests for your environment.

    • Export/import lists for rebuilds:

      winget export -o packages.json
      winget import -i packages.json –silent –accept-source-agreements –accept-package-agreements

  • Logging and monitoring:

    • Centralize logs to a file share or SIEM.
    • Use the script’s exit codes to alert on failures.
    • Periodically review the WinGet logs under the App Installer package folder.

Best Practices

  • Version pinning for stability:

    • Use winget pin to hold critical apps at a known stable version:

      winget pin add –id –version <x.y.z>
      winget pin list
      winget pin remove –id

    • Pin components that are sensitive (drivers, database clients, GPU tools) and update them intentionally.

  • Silent and non-interactive runs:

    • Always include –silent, –disable-interactivity, –accept-source-agreements, –accept-package-agreements in scheduled commands.
  • Keep sources healthy:

    • Periodically run:

      winget source update

    • If errors arise, repair with:

      winget source reset –force
      winget source update

  • Exclude or control problematic apps:

    • Some installers don’t support silent mode well. Exclude them or handle with app-specific logic.
    • Consider a separate maintenance window for those apps.
  • Reusable scripts and configuration:

    • Store Update-AllApps.ps1 under C:\ProgramData or a git repo.
    • Use consistent logging paths and rotate logs.
    • Optional: maintain a simple YAML/JSON with exclusions and pins.
  • Security and trust:

    • Only use trusted sources (winget, msstore, your internal source).
    • Avoid –ignore-security-hash unless you fully trust the binary and need a temporary workaround.
  • Validate after updates:

    • For critical machines, run smoke tests post-update (e.g., verify specific binaries or services are healthy).

Conclusion

Scheduling auto-updates for all apps with WinGet and Task Scheduler is a powerful, low-maintenance way to keep Windows systems secure and current. You learned how to:

  • Verify and prepare WinGet
  • Run a silent, unattended upgrade for all packages
  • Create Scheduled Tasks (GUI, schtasks, and PowerShell)
  • Add logging, exclusions, and optional YAML-driven configuration
  • Troubleshoot common issues
  • Apply best practices like version pinning and internal sources

Try the sample script and task setup today. WinGet is a safe, native solution that scales from a single workstation to a small fleet with minimal overhead.

FAQ

How often should I schedule WinGet auto-updates?

Daily during off-hours is a good default for most environments. Weekly might be sufficient for stable endpoints. Add a random delay to avoid network spikes in shared environments.

Can I run the Scheduled Task as SYSTEM?

It’s not recommended unless you have confirmed WinGet is available to the SYSTEM context. Because WinGet is distributed via the user-scoped App Installer, running as the same user who has WinGet installed is more reliable. If you must run as SYSTEM, test thoroughly.

How do I exclude a specific app from auto-updates?

Two common approaches:

  • Pin it:

    winget pin add –id

  • Extend the PowerShell script to skip particular PackageIds (see the optional YAML section).

Is it safe to use –include-unknown?

Yes, in many environments it helps catch upgrades where version detection is incomplete. However, it may attempt upgrades more aggressively. If you prefer strict version checks, omit –include-unknown.

What if some installers still pop up UI or require input?

Those packages may not fully support silent mode. Exclude them from the general auto-update task, handle with app-specific installer switches, or update them manually during a maintenance window.

About the author

Jonathan Dudamel

Jonathan Dudamel

I'm Jonathan Dudamel, an experienced IT specialist and network engineer passionate about all things Windows. I have deep expertise in Microsoft project management, virtualization (VMware ESXi and Hyper-V), and Microsoft’s hybrid platform. I'm also skilled with Microsoft O365, Azure ADDS, and Windows Server environments from 2003 through 2022.

My strengths include Microsoft network infrastructure, VMware platforms, CMMS, ERP systems, and server administration (2016/2022).