WinGet and IaC are maybe your next step to automate your environment. In the past, managing third-party applications on Windows meant 3rd party tools or gathering MSI installers on network shares, writing complex deployment wrappers, and battling silent installation switches that changed from vendor to vendor. I enjoyed that work a lot, but it is no longer a modern approach.
Microsoft’s WinGet package manager takes the package management concepts we’ve respected in Linux for decades and bakes them natively into the Windows ecosystem. But now with IaC it is time to say that WinGet has evolved massively. We are no longer just running basic install commands; we can deploy and standardize our Windows environments as code.
Table of Contents
Get started with WinGet and IaC on Windows 11 and Windows Server 2025
WinGet is integrated into modern Windows OS versions via the App Installer package. However, there is an operational catch: the WinGet tool typically only registers and becomes available after the first interactive login of a Windows user.
If you are automating a server deployment and WinGet is not available immediately, do not waste time rebooting. You can forcefully register the package with the following command:
Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbweSearch and Install Applications
With WinGet, installing and managing applications from the command line eliminates the need to hunt for vendor download pages. To see what is available, use the search command:
winget search sysinternalsOnce you identify the official product ID (usually Microsoft.Sysinternals), use the following command for a clean, automated installation. To execute without interactive prompts, you must accept the source and package agreements directly:
winget install --id Microsoft.Sysinternals --exact --accept-source-agreements --accept-package-agreements --silentWinget and Machine-Wide Install Scope
By default, many WinGet packages may attempt to install in the User Scope (under %LocalAppData%). On a Remote Desktop Session Host (RDS), Win11 multi-user system, or automated server, this is useless. You must explicitly define the scope to ensure the software is available to all users and resides in Program Files:
winget install --id Microsoft.Sysinternals --scope machineAlways use --scope machine for server automation to ensure consistent paths and availability across service accounts.
Important: Not all Winget Packages do support machine scope installation. Test carefully before deploying these.
Step 1 Winget and IaC – Export and Reproduce Environments
Before we use IaC level automatation lets move toward advanced automation and learn about the ability to clone an environment Winget Configuration.
Export a Snapshot:
winget export -o hartigade.json
Import on New Target:
winget import -i hartigade.json --accept-source-agreements --accept-package-agreementsImportant: : Use Export/Import for current status or call it snapshot replication. It’s a point-in-time copy of what is currently installed to another system
The IaC Standard: WinGet Configuration (DSC)
Today i focus on a new using WinGet Configuration. Microsoft has integrated PowerShell Desired State Configuration (DSC) v3 directly into WinGet. Instead of writing sequential install scripts, you declare the exact desired state in a YAML file. Check here for the official information from Microsoft.
To truly embrace the “Infrastructure as Code” (IaC) mindset, we need YAML config files. There are three primary ways to get your hands on a server-baseline.dsc.yaml file.
Recommend: Generate from an Existing Machine
If you have a “Gold Standard” server or a reference machine that is already configured exactly how you want it, you don’t need to write the YAML. You can let WinGet’s engine reverse-engineer the installed packages into a configuration file for you.
Run this command to capture the current state:
winget export -o server-baseline.dsc.yaml --include-versionsYou will then need to wrap this exported list into the DSC properties header (the properties: and resources: tags) to make it a valid configuration file. Check in the next chapter on how that template should look like.
Perfect way: Write your template
If you are starting from a blank slate, you create the file in a text editor like VS Code. Here is the minimal, functional template you need to get started. Copy this into a file named hartiga-baseline.dsc.yaml
# yaml-language-server: $schema=https://aka.ms/configuration-dsc-schema/0.2
properties:
configurationVersion: 0.2.0
resources:
- resource: Microsoft.WinGet.DSC/WinGetPackage
directives:
description: Install Sysinternals Suite
settings:
id: Microsoft.Sysinternals
source: winget
scope: machine # Ensure machine-wide install for servers
- resource: Microsoft.WinGet.DSC/WinGetPackage
directives:
description: Install 7zip (Pinned Version)
settings:
id: 7zip.7zip
version: 24.08
source: wingetExisting examples: Microsoft’s Configuration Gallery
For complex setups (like setting up a developer machine or a specific SQL server role), Microsoft and the community maintain a library of ready-to-use configurations.
You can find these on the Microsoft Dev Home repositories or by searching for “WinGet Configuration” on GitHub. Instead of reinventing the wheel, you download a .dsc.yaml from a trusted source and modify it to fit your organizational baselines, i.e. you can try https://github.com/dmealo/devboot to start with.
Understanding your WinGet and IaC Lifecycle
Step 1. Authoring: You create or edit the .dsc.yaml file.
Step 2. Testing (Validation):
You run
winget configure test -f .\hartiga-baseline.dsc.yamlto see if the server matches your requirements.
Step 3. Enforcement:
You run
winget configure -f .\hartiga-baseline.dsc.yamlto apply the changes.
By using this approach, you move away from “one-off” installs and toward a state where your servers are standardized, can easily auto update itself and is self-documenting.
Important: Use Configure (DSC) for state enforcement. It ensures the machine stays in the desired state over time.
WinGet Configuration (DSC) – Version Pinning
For controlled enterprise environments, “latest” isn’t always “greatest.” You need to pin versions to ensure compatibility and stability. In your DSC configuration, you can specify the exact version required:
# yaml-language-server: $schema=https://aka.ms/configuration-dsc-schema/0.2
properties:
configurationVersion: 0.2.0
resources:
- resource: Microsoft.WinGet.DSC/WinGetPackage
settings:
id: "Microsoft.Sysinternals"
version: "2024.9.0" # Version Pinning for Stability
source: wingetWinGet Configuration (DSC) – Drift Detection
One of the most valuable features of the modern WinGet stack is the ability to test compliance without making changes. This is essential for CI/CD pipelines and auditing:
winget configure test -f .\hartiga-baseline.dsc.yamlThis command allows you to detect configuration drift. If a technician manually uninstalled a tool or changed a version, this test will flag the machine as non-compliant, allowing you to remediate proactively.
Forcing Auto-Updates for the Windows Store
WinGet is updated via the Microsoft Store. On servers where the Store GUI is never opened, the App Installer package can become severely outdated, breaking your automation.
While you can target specific task names, names can vary across Windows builds. A safer, enterprise-grade approach to trigger these updates via PowerShell is to filter for the task dynamically:
Get-ScheduledTask -TaskPath "\Microsoft\Windows\WindowsUpdate\" | Where-Object {$_.TaskName -like "*App*"} | Start-ScheduledTaskWhen encountering issues or as a preperation you can risk this to guarantee that your WinGet and IaC environment remains fully capable of securing and configuring your Windows systems.
Conclusion on WinGet and IaC
Winget started as a replacement for 3rd party installer and update tools like patchmypc. Over the time it has evolved into a tool that is ready for Enterprise deployments using IaC and CI/CD pipelines. Start testing that functionality today. I am sure you will identify more than one use case to simplify your daily work.
To get started with Winget I highly recommend reading my original story here or check here with Thomas Maurer here or with Sarah Lean here.
If you have any questions please don’t hesitate to reach out to me on LinkedIn, Bluesky or check my newly created Adaptive Cloud community on Reddit.
LinkedIn: https://www.linkedin.com/in/andreas-hartig/
Bluesky: https://bsky.app/profile/hartiga.de
Adaptive Cloud community on Reddit: https://www.reddit.com/r/AdaptiveCloud/
Additional Resources
“Using the PowerShell WinGet module” by Harm Veenstra for an advanced insight into the PowerShell Winget module
Microsoft Learn on WinGet Configuration
Windows Dev Home (Out of Support but still a good place to start searching for Dev machines)
Find your Winget Packages here on Winget Run.