For years, the mantra of the desktop engineer has been the cycle of packaging, uploading, and assigning. We spend our days wrapping EXEs into .intunewin files, obsessing over detection rules, and praying that a reboot doesn’t break a complex dependency chain. It is an imperative workflow: we tell the system how to install a piece of software, but we rarely define the final state of the machine.
The introduction of WinGet Configuration changes this. By shifting from imperative scripts to a declarative YAML-based approach, Microsoft is bringing the “Infrastructure as Code” (IaC) philosophy to the endpoint. Instead of disjointed app assignments in Intune, you can now define a complete workstation persona that includes apps and system settings in a single .winget file.
The Shift from Imperative to Declarative Packaging
To understand why WinGet Configuration matters, you have to understand the difference between imperative and declarative management.
Imperative management is like a recipe. You download a file, run the installer with silent switches, and then move a folder. If any step fails or if the machine is already in a partial state, the script often fails or produces inconsistent results. This is how most Win32 app deployments in Intune work.
Declarative management is a blueprint. You specify that the machine should have Google Chrome version 120 and the ‘Developer Mode’ setting enabled. You don’t tell the system how to get there; you tell it what the end result should be. The engine (WinGet and PowerShell DSC) evaluates the current state and applies only the necessary changes to reach the target state.
For a packaging engineer, this reduces the dependency nightmare. Instead of creating multiple app packages and sequencing them via Intune’s supersedence, you define them as a collection of resources in one configuration file.
Anatomy of a .winget Configuration File
A .winget file is a YAML manifest that acts as the source of truth for a machine’s environment. It is split into two critical sections: Assertions and Resources.
Assertions: The Guardrails
Assertions are the preconditions. Before WinGet attempts to change the system, it checks the assertions. If an assertion fails, WinGet intelligently skips any resources that depend on that assertion.
For example, if your app stack requires Windows 11 22H2 to function, you define an OS version assertion. If a technician tries to run the config on a Windows 10 machine, the installation of the apps is skipped, preventing the machine from entering a broken state.
Resources: The Desired State
Resources are the actual items you want on the machine. While we typically think of resources as apps, WinGet Configuration uses PowerShell Desired State Configuration (DSC) to expand this.
A resource consists of:
- The Module: The PowerShell module responsible for the task (e.g.,
Microsoft.WinGet.DSC). - The Resource Type: The specific action (e.g.,
WinGetPackage). - Settings: The specific parameters (e.g., the App ID from the Winget repository).
- Directives: Metadata such as whether the resource requires elevated privileges (
securityContext: elevated).
Beyond the App: Integrating PowerShell DSC
The real power of WinGet Configuration is the ability to mix app installation with system configuration. Because it’s built on DSC, you can include resources that handle:
- Registry Keys: Ensure a specific software license key is present in
HKLM. - Environment Variables: Set
JAVA_HOMEorPATHvariables without writing separate PowerShell wrapper scripts. - Windows Features: Enable Hyper-V or WSL2 as a prerequisite for a developer toolset.
- Services: Ensure a specific background service is set to ‘Automatic’ and is running.
Imagine a “Developer Personas” file. In one file, you define WinGet packages for VS Code and Git, a DSC resource to enable Developer Mode, and an environment variable for the project’s build path.
When you run winget configure ./.config/dev-persona.winget, the system handles the orchestration. If the user already has VS Code installed but is missing the registry key, WinGet only applies the registry change.
Practical Workflow: Implementing a Standard Workstation
If you’re moving this into production, follow this practitioner’s workflow:
1. Define the Persona
Identify the requirements for a specific role. Don’t try to make one file for the whole company. Create separate files for roles like marketing, engineering, or HR.
2. Map Resources to IDs
Use winget search to find the exact IDs for the apps you need. Avoid using names; always use the unique ID (e.g., Microsoft.VisualStudioCode) to ensure the correct package is pulled.
3. Draft the YAML
Structure your file with clear logic. Place your OS assertions at the top, followed by system-level settings, and finally the application stack.
Example snippet:
resources:
- resource: Microsoft.Windows.Settings/WindowsSettings
directives:
securityContext: elevated
settings:
DeveloperMode: true
- resource: Microsoft.WinGet.DSC/WinGetPackage
id: vscode
settings:
id: Microsoft.VisualStudioCode
source: winget
4. Validate the Configuration
Before deploying, use the winget configure command in a test environment. Observe the logs to see how WinGet handles existing apps.
5. Distribution via Intune
While WinGet Configuration is a CLI tool, you can deploy it via Intune using a Win32 app wrapper. The “install” command for your wrapper would be:
winget configure --file C:\PathTo\your-config.winget
Enterprise Caveats and Limitations
There are several “gotchas” that every endpoint engineer needs to know:
The UAC Hurdle
WinGet Configuration handles elevation via the securityContext: elevated directive. However, if the user is not an administrator, they will still be prompted for UAC. To bypass this, you must run the winget configure command under the SYSTEM account via Intune.
The Community Repo Trust Gap
By default, WinGet pulls from the community repository. For high-security environments, this is a non-starter. You should configure a Private WinGet Source. This allows you to host your own vetted manifests, ensuring that winget configure only pulls from a source your security team has approved.
Dependency Sequencing
While dependsOn allows you to create a chain, complex circular dependencies can still cause issues. Keep your configuration files modular.
Conclusion: The Future of Endpoint as Code
The shift toward WinGet Configuration shows that the industry is moving away from imaging and scripting toward state management. By treating the workstation as code, we can version-control our environments in Git and deploy updates with a level of precision that imperative scripts can’t match.
For the packaging engineer, this means less time debugging why a script failed on a few machines and more time designing the ideal environment for the end user. The blueprint is now the product.