If every time you get new equipment you have to spend hours Installing programs, tweaking Windows, and setting up your development environmentIt's time to simplify. WinGet and YAML files let you turn that whole cumbersome process into a virtually automatic one that you can repeat on any PC with a single command.
The idea is to describe in a configuration file what you want to have installed and how your system should be configured, and then let it Windows Package Manager (winget) along with PowerShell Desired State Configuration (DSC) Do the dirty work: install software, apply settings, run scripts, and check that your machine is in just the right state to get you to work without wasting time.
What is WinGet and why is it so useful for automating your PC?
WinGet is Microsoft's official package manager for Windows 10 and Windows 11It works from the command line and allows you to install, update, configure and uninstall applications in a way very similar to what is done in GNU/Linux with apt, dnf or similar, but perfectly integrated into the Windows ecosystem.
Instead of searching for installers on hundreds of websites, downloading EXE or MSI files and clicking “Next, next, accept”, with WinGet you can launch a command like winget install package-name The system then downloads the program from a trusted source, performs the silent installation, and registers the package for future updates.
The main sources of software that WinGet uses are the Microsoft Store and the community repository hosted on GitHubwhere each application is described by a YAML manifest that indicates how to install it, its version, integrity hash, etc. Additionally, it's possible to add private repositories, such as one for your organization, to distribute internal software in a controlled manner.
The entire WinGet ecosystem is based on three pillars:
- La CLI winget (the command you use in the terminal).
- The services that host and validate packages.
- The YAML configuration files that allow you to declaratively define the desired state of an entire machine, not just individual applications.
Basic WinGet commands for managing applications
Before we delve into the technical aspects of YAML configuration files, it's helpful to understand the basics. basic WinGet commands for everyday useEverything is managed from PowerShell, Windows Terminal, or the classic command prompt.
If you simply write winget In a console, you'll see the installed version, available subcommands, and a summary of options. From there, you can start experimenting without fear.
To install an application You use the install subcommand. For example, to install Visual Studio Code on your PC, you would simply do:
winget install Microsoft.VisualStudioCode
In this case, Microsoft.VisualStudioCode is the exact package identifier in the WinGet repository. In many cases you can also install using the name exactly as it appears in the Store, in quotes if it has spaces, but using the ID reduces ambiguity.
If you would like to update your programsYou can ask WinGet to try to upload everything it recognizes with:
winget upgrade --all
Or you could focus on a specific app, for example:
winget upgrade Microsoft.VisualStudioCode
Modern versions of WinGet are able to update not only what it installed itself, but also applications it detects on the system that have an associated manifest in their origins.
To uninstall softwareThe mechanics are just as simple:
winget uninstall Microsoft.VisualStudioCode
The removal will work as long as WinGet has the program mapped in its catalog, either because it installed it or because it recognizes it through information registered in the system.
When you need to locate a program, you can use Winget searchFor example, to see what notepad options are available:
winget search notepad
The command will return a list with name, package ID, and origin (community repository, Store or private repository), and that ID is the one you should use in install or upgrade to be on the safe side.
If you want to know which software is controlling WinGet on your computer, you can use:
winget list
With this you will get a inventory of applications detected by the package manager. Very useful for deciding what to update or what to include in your configuration files.
Automating installations with YAML files: the beauty of it all
The really interesting part comes when you go from typing commands one by one to Describe your ideal environment in a single YAML fileInstead of having a cheat sheet of commands or a fragile script, you declaratively define how you want the machine to look and delegate the work to WinGet and DSC.
A WinGet configuration file contains the list of packages, versions, tools, scripts, and system settings that you need for your development environment (or for the entire company). It's not just limited to installing programs: it can activate Windows features, tweak the registry, manage services, launch PowerShell scripts… Everything necessary to put the PC in a specific state.
For this to work, you need to have a sufficiently recent version of WinGet, specifically v1.6.2631 or higherThis is when integration with DSC 3.0 and the winget configure command, responsible for processing the YAML configuration files, are introduced in a stable manner.
The advantage is that the process becomes unattended and repeatableYou execute a command, accept the necessary agreements, and you can go grab a coffee while the system installs everything needed, adjusts Windows, configures your IDEs, and gets the environment ready to use. And if you change PCs tomorrow, you just repeat the process and you're good to go.
Furthermore, these files can save it to a Git repository, OneDrive, or wherever you want, share with your team, version changes, open issues and pull requests… In short, treat your machine's configuration as code (IaC) and not as something manual and unrepeatable.
The winget configure command and its main options
The gateway to the entire declarative system is the command winget configure. This is responsible for reading your WinGet configuration file, validating that it is correct, downloading the necessary PowerShell modules, and applying the changes.
Before diving in, it's advisable enable configuration components (if they are not already active) with:
winget configure --enable
Once that's done, the most sensible thing to do is start by validating the YAML file with the command:
winget configure validate -f ruta\a\archivo.winget
The validation checks both the YAML syntax as JSON schema compliance official configuration. Keep in mind that YAML is sensitive to indentation (spaces, not tabs), so editing these files in Visual Studio Code with the Red Hat YAML extension and the linked WinGet schema is almost mandatory to avoid going crazy.
When everything looks good, you can Apply the settings seriously with:
winget configure --file ruta\a\archivo.winget --accept-configuration-agreements
At that point, the configuration processor comes into play, interpreting the YAML, downloading any missing DSC modules from the PowerShell Gallery, and starting to execute assertions and resources. Tasks that allow it are executed in parallel. Those that require Administrator privileges will trigger a UAC warning at launch for elevation.
If you prefer to do a "dry test" before changing anything, you can use:
winget configure test -f ruta\a\archivo.winget --accept-configuration-agreements
With test, WinGet evaluates the system by comparing it to the desired state described in the file and It tells you what things don't add up.without even touching the machine yet. This is very useful for adjusting complex settings and ensuring that there will be no surprises when applying the file.
It is also possible to work with remote files, for example hosted in a public or private repository, by running something like:
winget configure --accept-configuration-agreements --disable-interactivity -f https://tu-servidor/tu-config.winget
This usage method fits very well in scenarios of mass deployment or centralized administrationwhere IT publishes a configuration and users or scripts only have to run a command to leave the corporate computer with the defined standard.
Arguments, options, and subcommands of winget configure
The configure subcommand supports a number of parameters for fine-tuning behaviorSome of the most relevant ones are:
- -f, –file. Path to the WinGet configuration file to be applied.
- –module-path. Local folder where the downloaded DSC modules will be stored (by default in %LOCALAPPDATA%\Microsoft\WinGet\Configuration\Modules).
- –processor-path. Location of a custom configuration processor, if applicable.
- –accept-configuration-agreements. Accept the configuration warning in advance to avoid an interactive notification.
- –suppress-initial-details. Try hiding the initial setup details for a cleaner output.
- –enable / –disable. Enable or disable configuration components (requires access to the Store).
- –logs, –open-logs. Open the folder where the configuration logs are stored.
- –verbose, –verbose-logs. Enables detailed logging for troubleshooting.
- –nowarn, –ignore-warnings. Suppress warning messages on the exit.
- –disable-interactivity. It prevents any type of interactive prompt, ideal for unattended scripts.
- –proxy / –no-proxy. It allows you to define a proxy for that specific execution or disable the use of a proxy.
In addition to the main command, winget configure has several subcommands What should be known:
- winget configure show -f . Displays details of a specific configuration file, useful for inspecting it without opening it in an editor.
- winget configure list. It displays a summary of the configurations that have been applied to the system, which helps to keep track of what has been run.
- winget configure test -f . Verification mode that compares the current state of the system with the one defined in the configuration.
- winget configure validate -f . Validate only the file, without touching the machine.
- winget configure export -o . It allows exporting configuration resources to a file, whether it's all package configurations (
--all), a specific package (--package-id) or a specific resource (--moduley--resource), appending to the output file if it already exists.
WinGet configuration file format and naming convention
WinGet configuration files use YAML format with an associated JSON schema which defines the valid structure. WinGet's own manifest system is also based on YAML. So everything fits within the same model.
By convention, these files are saved with the extension .winget, for example configuration.wingetIn projects using Git, it is generally recommended to store them in a hidden directory. .configleaving routes like ./.config/configuration.winget for the project's "default" configuration.
If your project uses different combinations of tools or preferences, you can keep several configuration files in the same folder, each with a descriptive name that indicates which environment it uses (for example, frontend.winget, backend.winget, etc.).
The first line of the file is usually a special comment to let editors know which JSON schema to use. It typically looks something like this:
# yaml-language-server: $schema=https://aka.ms/configuration-dsc-schema/0.2
In the base direction https://aka.ms/configuration-dsc-schema/ You can check the latest schema version and update your file when Microsoft releases new revisions with more capabilities.
After that header, the root node of the document is always propertieswhich must include a field configurationVersion (for example 0.2.0) and the two main sections that structure everything: assertions y resources.
Structure of a configuration file: properties, assertions, and resources
Under the node properties On the one hand, it is declared that configurationVersionwhich you should increase as the file evolves, and on the other hand the collections assertions y resources that describe the behavior.
- The section assertions. It encompasses the assertions or preconditions that must be met for certain resources to be meaningful: minimum Windows version, presence of a certain feature, etc. They are not actions in themselves, but rather environment checks.
- The section resources. It gathers all the configuration resources you intend to apply: software installations, system settings, scripts, service management, registry changes, etc. Each item in these lists is represented by a node of type
resourcewith the necessary information.
In both cases, Each entry is defined by indicating the DSC resource to be used, with the format {NombreModulo}/{NombreRecursoDSC}. For example, Microsoft.Windows.Settings/WindowsSettings to touch Windows settings, or Microsoft.WinGet.DSC/WinGetPackage to install a WinGet package from DSC.
Along with the resource field, each unit usually includes sections of directives and settings, an optional identifier id and, when necessary, a list of dependencies dependsOn towards other resources or assertions.
Assertions: Check Windows version and other prerequisites
The Assertions act as pre-filters that decide whether it makes sense to run certain resources on the current machine. This way, you don't try to install or configure something on a system that doesn't meet the basic requirements.
A typical example is checking the minimum operating system versionMany configurations require at least Windows 10 1809 or a specific build of Windows 11, and it's pointless to proceed if you're on an older version that doesn't even support WinGet.
An assertion of this style uses DSC resources such as Microsoft.Windows.Developer/OsVersion, indicating a property via settings MinVersion (for example '10.0.22000') which defines the acceptable threshold for the configuration.
Assertions can evaluate in parallelwithout a strict order, and essentially return a true or false state. If the assertion returns false (is not fulfilled), any resource that includes it as a dependency through dependsOn It will be automatically omitted.
This behavior is considered a correct outcome from the declarative system's perspective: it's better to skip a block that doesn't make sense than to force its execution in an unsuitable environment. The output messages might show something like, "A resource was not executed because an assertion failed or was false."
Even if some of the settings don't apply, WinGet will still attempt to apply them. continue with other independent resources to bring the system as close as possible to the desired state. At the end, you are responsible for reviewing the errors and deciding whether to change the configuration or the environment.
Resources: Installing packages, tweaking Windows, and launching scripts
The section resources is the practical heart of the configuration fileHere you list everything you want to happen on the machine: software installation, system configuration changes, running PowerShell scripts, service management, etc.
Each resource is defined with a field resource that follows the form Modulo/RecursoDSC, for example Microsoft.Windows.Settings/WindowsSettings to activate system functions, or Microsoft.WinGet.DSC/WinGetPackage to orchestrate the installation of a package via WinGet from DSC.
Optionally, you can assign a unique ID which will help you to reference it from dependsOn in other resources. This is very useful when you want, for example, the configuration of extra Visual Studio components to explicitly depend on Visual Studio itself being installed beforehand.
Within each resource, the section directives contains contextual information on how it should be executed: textual description of the task (description), if preview modules are accepted from PowerShell Gallery (allowPrerelease) And the securityContext which indicates whether the execution requires elevated privileges.
When you put securityContext: elevatedWinGet will request administrator permissions once at the start of the setup and from then on it will be able to run elevated and non-elevated resources using different processes, without bombarding you with more UAC windows.
The section settings define the name-value pairs that are passed to the DSC resource. It can be something as simple as DeveloperMode: true to activate Windows developer mode, or more complex parameters such as id y source from a WinGet package, the path to a .vsconfig file, a specific registry value, or the details of a service that needs to be enabled.
Finally, the field dependsOn It allows you to declare that this resource should only be executed when certain prior assertions or resources have successfully completed. If one of those dependencies fails, the resource is automatically marked as not executed or failed, preventing unwanted side effects.
Organize the resources section in a readable way
In large projects, configuration files can grow quite large, so it's worth taking the time to do so. Think a little about how you organize the resources section so that it remains maintainable over time.
A common strategy is to organize resources according to a logical order of execution:
- First, what the system prepares (assertions, basic updates).
- Then generic tools (browsers, compressors, utilities).
- Then IDE and SDK.
- Finally, more specific scripts or settings.
Another interesting approach is to group them by probability of failure or complexityIn other words, put the tasks that most often break down (heavy installations that depend on a good connection or credentials) at the beginning, so that the user realizes early on that something is wrong without waiting for everything to finish.
Many prefer to group by type of resourceFirst, the WinGet package, then Windows configurations (registry, features, services), then scripts, and finally, tools specific to a particular project. This style often resembles the typical structure of a software project and helps you get your bearings quickly.
Whatever the criteria, it is highly recommended to accompany the file with a README in the repository explaining the configuration structure, key dependencies, minimum required Windows versions, and recommended execution steps.
That documentation makes it so that Other developers can contribute to the archive with less risk. to break something, since they better understand what each block does and what assertions or dependsOn are at play before adding a new resource.
Using the ${WinGetConfigRoot} variable in file paths
Many DSC resources accept parameters that expect paths to specific filesVisual Studio configurations, scripts, templates, etc. If you use absolute paths, your file loses portability as soon as you change users, drives, or folders.
To prevent this, WinGet introduces the variable ${WinGetConfigRoot}, which points to the directory from which you are running winget configureFrom there you can build relative paths that will work the same on any computer where the same folder structure is respected.
If, for example, you save the configuration file in .config/configuration.winget and the file .vsconfig In the repository root, you can use a path like '${WinGetConfigRoot}\..\.vsconfig'. The part .. Go up one level from the working folder and drop you right into the directory where .vsconfig lives.
This technique makes it so that the same configuration is valid for all members of a team that clone the project to different paths, as long as they respect the relative placement of the files within the repo.
However, it's worth remembering in the README that The user must ensure that the target file exists. in the relative path that expects the configuration before launching winget configure, or the execution will flag errors on those resources.
Where to find DSC modules and ready-to-use resources
For this whole system to work, WinGet relies on PowerShell modules that implement DSC resourcesSome come "by default" with the system itself (the so-called inbox resources) and others are obtained from the PowerShell Gallery.
Among the standard resources you have modules to manage environment variables, install or uninstall MSI packages (msiPackage), manipulate registry keys and values (Registry), run script blocks (Script), control Windows services (Service), add or remove roles and features (WindowsFeature), or start and stop processes (WindowsProcess).
La PowerShell Gallery houses hundreds of additional modules with DSC resources contributed by the community. You can use the search filters to show only those marked as “DSC Resource” and thus locate reusable parts for your configurations.
However, it's important to keep in mind that the gallery is not a fully audited environment: Anyone can publish modulesand some may include risky or outright malicious scripting if not carefully reviewed.
For that reason, Microsoft insists that the origin and content of the modules before using them in configurations that will run on production machines, especially if those resources run with a high security context.
To see concrete examples of configuration files, Microsoft maintains a DSC WinGet and YAML configuration repository accessible via the short link https://aka.ms/dsc.yaml, where you can find inspiration and use already tested templates as a base.
Security, trust, and group policies related to WinGet
Since WinGet and DSC can install and configure software in bulkThe security aspect is fundamental, especially in corporate environments where there are quite strict compliance requirements.
WinGet integrates with the Microsoft Store via origin msstore and employs techniques of certificate pinning to verify that the Store's HTTPS certificate matches one of the known certificates and thus prevent man-in-the-middle (MITM) attacks.
In organizations that use firewalls with SSL inspection, this behavior can cause problems if the security appliance repackages the connection with its own certificate. For such cases, there is a policy called BypassCertificatePinningForMicrosoftStore which allows you to specify whether WinGet should skip that check.
Possible options include leaving the policy unconfigured (respecting the default recommended behavior), enabling it so that WinGet Do not validate the Store certificate or explicitly disable it to force it to only accept known Microsoft certificates.
Disable certificate anchoring increases the risk of man-in-the-middle attacksTherefore, it should only be done with full knowledge of the facts and when there is no reasonable alternative, fitting it within an overall security strategy.
In addition to this directive, there are WinGet-specific group policy templates (.admx and .adml files) that allow administrators control allowed or blocked sources, enable or disable experimental features, define behavior towards proxies and, in general, shape how the package manager behaves within the organization.
These templates are distributed within the package DesktopAppInstallerPolicies.zip in the WinGet GitHub repository. Once decompressed, the files are copied to C:\Windows\PolicyDefinitions The corresponding language folder is now available, so it can be managed from the group policy management console.
There are also group policy objects such as EnableWindowsPackageManagerConfiguration and EnableWindowsPackageManagerConfigurationExplanation which allow blocking the use of WinGet configuration files across the entire organization, in case it is considered that this functionality should be strictly limited.
Additional repositories and use of private sources in WinGet
Out of the box, WinGet uses the following as its main sources: the Microsoft Store and the community repository on GitHubwhere you can find manifests for tons of popular programs: browsers, development suites, design tools, various utilities, etc.
However, many companies need something more: private repositories where you can host your own applications, internal packages, validated versions of certain tools, or filtered catalogs that comply with their policies.
WinGet allows you to register additional sources using the command:
winget source add --name <nombre_del_repositorio> --arg <URL_del_repositorio>
This origin is usually of type REST by default, although you can specify it with --type If you need it. Additionally, there are parameters such as –trust-level to define the level of trust (none or trusted) and –accept-source-agreements to automatically accept the source license agreements, which is essential when automating the incorporation of repositories.
To check which fonts you currently have on your computer, you can run:
winget source list
This command returns all available sources with their name and type. From that point on, WinGet searches and installations will take into account the additional repositories according to your configured settings.
There are projects that offer Ready-to-deploy solutions for private WinGet repositories in Azure or on-premises installations using Docker, which offers considerable flexibility when setting up corporate catalogs or controlled environments where only IT-approved software exists.
In practice, combining private repositories with well-designed YAML configuration files allows fully standardize the software and equipment configuration of a company, with the peace of mind that everything comes from an origin that you yourself control.
With all of the above, WinGet, its YAML configuration files, and DSC resources turn the tedious task of preparing and maintaining Windows PCs into a process much faster, repeatable and saferWhether you're a developer who wants to clone your environment across multiple computers or you manage a fleet of computers in an organization and want to stop doing everything manually.

