WinGet Configuration v2 → v3 Conversion Skill
You are an expert at converting WinGet Configuration files from DSC schema v0.2 (v2) to the dscv3 processor syntax (v3). Follow these rules precisely.
Document Structure
v2 structure
# yaml-language-server: $schema=https://aka.ms/configuration-dsc-schema/0.2
properties:
configurationVersion: 0.2.0
assertions:
- resource: ...
resources:
- resource: ...
v3 structure
$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json
metadata:
winget:
processor:
identifier: dscv3
resources:
- type: ...
Key changes:
- Remove the
properties:wrapper andconfigurationVersion - Remove
assertions:section (v3 does not support assertions in the same way) - Add
$schemapointing to the DSC v3 schema - Add
metadata.winget.processor.identifier: dscv3 - Resources move to a top-level
resources:array
Field Renaming
Apply these renames to every resource:
| v2 Field | v3 Field |
|---|---|
resource: |
type: |
id: |
name: |
settings: |
properties: |
directives: |
metadata: |
Example
v2:
- resource: Microsoft.WinGet.DSC/WinGetPackage
id: git
directives:
description: Install Git
allowPrerelease: true
settings:
id: Git.Git
source: winget
v3:
- type: Microsoft.WinGet/Package
name: Git
properties:
id: Git.Git
source: winget
useLatest: true
metadata:
description: Install Git
Resource Type Mapping
| v2 Resource Type | v3 Resource Type | Notes |
|---|---|---|
Microsoft.WinGet.DSC/WinGetPackage |
Microsoft.WinGet/Package |
Renamed |
PSDscResources/Registry |
Microsoft.Windows/Registry |
Use native v3 resource — dramatically faster |
PSDscResources/Script |
Microsoft.DSC.Transitional/RunCommandOnSet |
Or PowerShellScript/WindowsPowerShellScript if test support needed |
PSDscResources/WindowsOptionalFeature |
Microsoft.Windows/OptionalFeatureList |
Native v3, batch multiple features in one resource |
Microsoft.Windows.Developer/* |
Microsoft.Windows.Developer/* |
Unchanged (adapted resource, requires module install) |
Microsoft.Windows.Settings/* |
Microsoft.Windows.Settings/* |
Unchanged (adapted resource, requires module install) |
CRITICAL: Always prefer Microsoft.Windows/Registry over PSDscResources/Registry.
The native v3 resource evaluates in ~3 seconds per key with linear scaling. The adapted
PSDscResources/Registry takes 89–228 seconds per key with super-linear growth. For a
configuration with 22 registry keys, this is the difference between ~2 minutes and 30+ minutes.
Using the native resource also eliminates the need to install the PSDscResources module.
Package Resources (Microsoft.WinGet/Package)
Properties changes
- Add
useLatest: trueto properties (replaces the concept of always getting latest) - Remove
allowPrerelease: truefrom directives/metadata (this was a v2 directive) - The
source: wingetproperty remains the same
Security Context / Elevation
CRITICAL: Do NOT blindly add securityContext: elevated to package installs.
Before adding securityContext: elevated to any package resource, check the package's
installer manifest in the microsoft/winget-pkgs repository for the ElevationRequirement field:
elevationRequired→ Yes, addsecurityContext: elevatedelevatesSelf→ No, the installer handles its own UAC prompt- No
ElevationRequirementfield → No, elevation is not needed - Portable/zip installers → No, never need elevation
- MSIX installers → No, never need elevation
To check, look up the installer manifest at:
manifests/<first-letter>/<Publisher>/<Package>/<Version>/<Id>.installer.yaml
When elevation IS needed, add it in metadata:
metadata:
winget:
securityContext: elevated
description: ...
Common packages and their elevation requirements
| Package | ElevationRequirement | Needs elevated? |
|---|---|---|
| Git.Git | elevatesSelf | No |
| GitHub.Cli | elevatesSelf | No |
| GitHub.Copilot | None (portable) | No |
| Microsoft.PowerShell | elevatesSelf (MSI) | No |
| Microsoft.VisualStudioCode | None | No |
| Python.Python.3.x | elevatesSelf (machine) | No |
| astral-sh.uv | None (portable) | No |
| OpenJS.NodeJS | elevatesSelf | No |
| JanDeDobbeleer.OhMyPosh | None (MSIX) | No |
| Microsoft.PowerToys | elevatesSelf (machine) | No |
| Microsoft.WSL | None | No |
| Canonical.Ubuntu | None (MSIX) | No |
Class-Based DSC Resources (PowerShell Modules)
In v2, PowerShell class-based DSC resources (like PSDscResources/Registry,
Microsoft.Windows.Developer/*, Microsoft.Windows.Settings/*) are handled
automatically by the WinGet DSC processor.
In v3, the dscv3 processor does NOT know about v2-style PowerShell DSC resources.
You must explicitly install the PowerShell modules using
Microsoft.DSC.Transitional/RunCommandOnSet before any resources that depend on them.
Required module installs
For each PowerShell DSC module used, add a RunCommandOnSet resource that installs it. All module installs depend on PowerShell 7 being installed first.
CRITICAL: Only use -AllowPrerelease when no stable version exists on the PowerShell Gallery.
Check the PowerShell Gallery before adding -Prerelease:
Find-PSResource -Name <ModuleName> # Check for stable
Find-PSResource -Name <ModuleName> -Prerelease # Check for prerelease
Known module status (verify before use — this may change)
| Module | Stable Available? | Needs -AllowPrerelease? |
|---|---|---|
| PSDscResources | Yes (2.12.0.0) | No |
| Microsoft.Windows.Settings | No (alpha only) | Yes |
| Microsoft.Windows.Developer | No (alpha only) | Yes |
Module install pattern
Use Install-PSResource (built into PowerShell 7) rather than the older Install-Module:
- type: Microsoft.DSC.Transitional/RunCommandOnSet
name: Microsoft.Windows.Developer.Module
dependsOn:
- PowerShell
properties:
executable: C:\Program Files\PowerShell\7\pwsh.exe
arguments:
"0": -NoProfile
"1": -NoLogo
"2": -Command
"3": >-
if (-not (Get-Module -ListAvailable -Name Microsoft.Windows.Developer))
{ Install-PSResource -Name Microsoft.Windows.Developer -Prerelease
-TrustRepository -AcceptLicense }
treatAsArray: true
metadata:
description: Ensure Microsoft.Windows.Developer module is installed
For modules with a stable release (no -Prerelease flag needed):
"3": >-
if (-not (Get-Module -ListAvailable -Name PSDscResources))
{ Install-PSResource -Name PSDscResources
-TrustRepository -AcceptLicense }
Dependency chain
Resources using these modules MUST have dependsOn pointing to the module install resource:
- type: Microsoft.Windows.Developer/EnableLongPathSupport
name: LongPaths
dependsOn:
- Microsoft.Windows.Developer.Module
properties:
Ensure: Present
metadata:
winget:
securityContext: elevated
description: Enable Win32 long paths
PSDscResources/Script → RunCommandOnSet
v2 PSDscResources/Script resources have GetScript, TestScript, and SetScript blocks.
In v3, these become Microsoft.DSC.Transitional/RunCommandOnSet which only runs
the set logic. Combine the test and set logic into the command argument.
Alternative: If you need proper test/get/set separation, use
Microsoft.DSC.Transitional/PowerShellScript(runs in pwsh 7) orMicrosoft.DSC.Transitional/WindowsPowerShellScript(runs in Windows PowerShell 5.1). These havegetScript,testScript, andsetScriptproperties and can properly report whether the system is already in the desired state. Performance is comparable to RunCommandOnSet.
Example conversion
v2:
- resource: PSDscResources/Script
id: ps7default
dependsOn:
- powershell
directives:
description: Set PowerShell 7 as default Windows Terminal profile
settings:
GetScript: |
return @{ Result = $false }
TestScript: |
# test logic here
return $false
SetScript: |
# set logic here
v3:
- type: Microsoft.DSC.Transitional/RunCommandOnSet
name: ps7default
dependsOn:
- PowerShell
properties:
executable: C:\Program Files\PowerShell\7\pwsh.exe
arguments:
"0": -NoProfile
"1": -NoLogo
"2": -Command
"3": |
# Combined test + set logic here
treatAsArray: true
metadata:
description: Set PowerShell 7 as default Windows Terminal profile
Registry Resources — Use Native Microsoft.Windows/Registry
CRITICAL: Convert all PSDscResources/Registry to Microsoft.Windows/Registry.
The native v3 resource is a completely different (and far superior) resource:
- No PowerShell module install needed
- No adapter overhead
- ~3 seconds per key vs 89–228 seconds
- Linear scaling vs super-linear growth
Property mapping
v2 (PSDscResources/Registry) |
v3 (Microsoft.Windows/Registry) |
Notes |
|---|---|---|
Key: HKLM:\SOFTWARE\... |
keyPath: HKLM\SOFTWARE\... |
Drop the :\ — use HKLM\ not HKLM:\ |
Key: HKCU:\SOFTWARE\... |
keyPath: HKCU\SOFTWARE\... |
Drop the :\ — use HKCU\ not HKCU:\ |
ValueName: Name |
valueName: Name |
camelCase |
ValueType: DWord + ValueData: '3' |
valueData: { DWord: 3 } |
Type is embedded in the data object |
ValueType: String + ValueData: text |
valueData: { String: "text" } |
Type is embedded in the data object |
ValueType: QWord + ValueData: '0' |
valueData: { QWord: 0 } |
Type is embedded in the data object |
Ensure: Present |
_exist: true |
Different existence model |
Ensure: Absent |
_exist: false |
Different existence model |
Force: true |
(not needed) | Native resource handles this |
dependsOn: [PSDscResources.Module] |
(not needed) | No module dependency |
Conversion example
v2:
- resource: PSDscResources/Registry
id: sudo
directives:
description: Enable Sudo in inline mode
allowPrerelease: true
securityContext: elevated
settings:
Key: HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Sudo
ValueName: Enabled
ValueType: DWord
ValueData: '3'
Force: true
Ensure: Present
v3:
- type: Microsoft.Windows/Registry
name: Sudo
properties:
keyPath: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Sudo
valueName: Enabled
valueData:
DWord: 3
_exist: true
metadata:
winget:
securityContext: elevated
description: Enable Sudo in inline mode
Value data types
| Registry Type | v3 Format | Example |
|---|---|---|
| DWord | valueData: { DWord: 3 } |
32-bit integer |
| QWord | valueData: { QWord: 0 } |
64-bit integer |
| String | valueData: { String: "text" } |
String value |
| ExpandString | valueData: { ExpandString: "%PATH%" } |
Expandable string |
| MultiString | valueData: { MultiString: ["a", "b"] } |
Array of strings |
| Binary | valueData: { Binary: [0, 1, 2] } |
Array of bytes |
| None | valueData: None |
No data |
Elevation rules for Registry
HKLM\keys → addmetadata.winget.securityContext: elevatedHKCU\keys → no elevation needed
Security Context in v3
In v2, elevation was specified per-resource in directives.securityContext.
In v3, elevation is specified in metadata.winget.securityContext:
metadata:
winget:
securityContext: elevated
description: ...
Resources that typically need elevation:
- Registry keys under
HKLM:\ Microsoft.Windows.Developer/EnableLongPathSupportMicrosoft.Windows.Developer/EnableRemoteDesktopMicrosoft.Windows.Developer/UserAccessControlMicrosoft.Windows.Settings/WindowsSettings(for DeveloperMode)
Resources that typically do NOT need elevation:
- Registry keys under
HKCU:\ Microsoft.Windows.Developer/WindowsExplorerMicrosoft.Windows.Developer/Taskbar- Most
Microsoft.WinGet/Packageinstalls (check manifest first)
Name Casing Convention
In v2, resource id: values are typically lowercase (e.g., git, vscode, powershell).
In v3, resource name: values should use PascalCase (e.g., Git, VSCode, PowerShell).
Dependencies
dependsOn references must use the v3 name: value (PascalCase), not the v2 id: value.
v2: dependsOn: [git]
v3: dependsOn: [Git]
Performance Considerations
When converting, be aware of the evaluation time costs of different resource types:
| Resource Type | Approx. Eval Cost | Scaling | Notes |
|---|---|---|---|
Microsoft.WinGet/Package |
~8–16s each | Linear | Efficient native resource |
RunCommandOnSet |
~5s each | Linear | Lightweight |
PowerShellScript / WindowsPowerShellScript |
~5s each | Linear | Same cost as RunCommandOnSet, but supports test |
Microsoft.Windows/Registry (native v3) |
~3s each | Linear | Preferred for all registry operations |
Microsoft.Windows.Settings/* (adapted) |
~95s each | Variable | Class-based, requires adapter |
Microsoft.Windows.Developer/* (adapted) |
~30–122s each | Super-linear | Expensive, especially when elevated |
PSDscResources/Registry (adapted) |
~89–228s each | Super-linear | Avoid — use Microsoft.Windows/Registry instead |
Fixed overhead for dscv3 processor startup is approximately 23 seconds.
Key optimization: Replacing
PSDscResources/RegistrywithMicrosoft.Windows/Registryis the single highest-impact optimization when converting a v2 config to v3. A config with 22 registry keys drops from 30+ minutes to under 2 minutes for registry evaluation alone. This also eliminates the need to install the PSDscResources PowerShell module.
Windows Optional Features (Microsoft.Windows/OptionalFeatureList)
A native v3 resource (no adapter needed) for enabling/disabling Windows Optional Features.
| Property | Type | Description |
|---|---|---|
features |
array | List of feature objects |
features[].featureName |
string | Windows feature name |
features[].state |
enum | Installed, NotPresent, Removed |
Common feature names (not intuitive — use these exact strings):
Containers-DisposableClientVM→ Windows SandboxMicrosoft-Hyper-V-All→ Hyper-V (all components)VirtualMachinePlatform→ Virtual Machine PlatformMicrosoft-Windows-Subsystem-Linux→ WSL
- type: Microsoft.Windows/OptionalFeatureList
name: WindowsFeatures
properties:
features:
- featureName: Containers-DisposableClientVM
state: Installed
- featureName: Microsoft-Hyper-V-All
state: Installed
metadata:
winget:
securityContext: elevated
description: Enable Windows Sandbox and Hyper-V
v2 equivalent uses PSDscResources/WindowsOptionalFeature (one resource per feature).
Operational Notes for Testing and Automation
- v2 module caching: WinGet v2 caches modules at
%LOCALAPPDATA%\Microsoft\WinGet\Configuration\Modules\— separate from$env:PSModulePath. Modules here can become stale. - v3 uses standard PS paths: The dscv3 processor uses
$env:PSModulePath. Modules must be installed explicitly viaInstall-PSResourcein aRunCommandOnSetresource before use. - Concurrent operations blocked: Never run two
winget configurecommands simultaneously — WinGet prevents parallel runs. --disable-interactivitydoes not suppress the progress spinner. Stdout is flooded with ANSI sequences.- Adapter resources work in v3: dscv3 processor handles PowerShell adapter resources (GitDsc, StorageDsc, etc.) when modules are in the standard PS path.
- PowerToys: v2 DSC resources are deprecated. Use native v3
Microsoft.PowerToys/*resources.
Conversion Checklist
When converting a v2 configuration to v3:
- Update document structure (
$schema,metadata.winget.processor, removeproperties:wrapper) - Rename all fields (
resource→type,id→name,settings→properties,directives→metadata) - Update resource type names (
Microsoft.WinGet.DSC/WinGetPackage→Microsoft.WinGet/Package) - Add
useLatest: trueto all package resources - Check each package's WinGet manifest for
ElevationRequirementbefore addingsecurityContext: elevated - Convert all
PSDscResources/Registryto nativeMicrosoft.Windows/Registry(key path format, valueData typed objects,_existinstead ofEnsure) - Add PowerShell module install resources for any remaining adapted class-based DSC resources (Settings, Developer)
- Use
Install-PSResource(notInstall-Module) for module installs — it ships with PowerShell 7 - Check PowerShell Gallery for each module — only use
-Prereleasewhen no stable version exists - Add
dependsOnfrom each adapted resource to its module install resource - Convert
PSDscResources/ScripttoRunCommandOnSet(orPowerShellScript/WindowsPowerShellScriptif test support is needed) - Update
dependsOnreferences to use PascalCasename:values - Apply
securityContext: elevatedonly to HKLM registry keys and system-level settings that require it - Remove
allowPrerelease: truefrom resource metadata (v2 directive, not used in v3) - Remove
PSDscResources.Moduleinstall resource if all Registry resources are converted to native v3
Source: microsoft/winget-dsc — distributed by TomeVault.