What Is PowerShell Desired State Configuration?
PowerShell Desired State Configuration (DSC) is a declarative management platform built into Windows PowerShell and PowerShell 7. Instead of writing imperative scripts that execute a sequence of commands, DSC lets you describe the desired end state of a system — which Windows features should be installed, which services should be running, which files should exist — and the DSC engine handles bringing the actual state into compliance with the desired state.
DSC is particularly powerful for Windows Server 2022 environments where consistent, repeatable server configuration is required across many nodes. It is commonly used for initial server provisioning, configuration drift detection, automated remediation, and compliance enforcement. DSC integrates with tools like Azure Automation, Ansible, and Chef as a configuration backend.
DSC operates through three components: configurations (the PowerShell scripts describing the desired state), resources (the modules that implement how to check and enforce each aspect of state), and the Local Configuration Manager (LCM), which is the DSC engine on each target node responsible for applying configurations.
Discovering DSC Resources
DSC resources are the building blocks of configurations. Each resource represents a manageable aspect of a system — a Windows feature, a file, a registry key, a service. Windows Server 2022 includes a set of built-in DSC resources. Additional resources are available from the PowerShell Gallery as part of modules like PSDesiredStateConfiguration, NetworkingDsc, and ComputerManagementDsc.
List all available DSC resources on the local system:
Get-DscResource
Get detailed information about a specific resource including its properties:
Get-DscResource -Name File -Syntax
Install additional DSC resource modules from the PowerShell Gallery:
Install-Module -Name NetworkingDsc -Force
Install-Module -Name ComputerManagementDsc -Force
Install-Module -Name PSDesiredStateConfiguration -Force
Verify resources from an installed module are available:
Get-DscResource -Module NetworkingDsc
Writing a Basic DSC Configuration
A DSC configuration is a PowerShell script block preceded by the Configuration keyword. Inside the block, you declare Node sections (targeting specific servers) and resource blocks defining the desired state. The following example configures a web server node to have IIS installed, the W3SVC service running, and a specific directory present:
Configuration WebServerConfig {
param (
[string[]]$ComputerName = 'localhost'
)
Import-DscResource -ModuleName PSDesiredStateConfiguration
Node $ComputerName {
WindowsFeature IIS {
Name = 'Web-Server'
Ensure = 'Present'
}
WindowsFeature ASP {
Name = 'Web-Asp-Net45'
Ensure = 'Present'
DependsOn = '[WindowsFeature]IIS'
}
Service W3SVC {
Name = 'W3SVC'
State = 'Running'
StartupType = 'Automatic'
DependsOn = '[WindowsFeature]IIS'
}
File WebRoot {
DestinationPath = 'C:inetpubwwwrootapp'
Type = 'Directory'
Ensure = 'Present'
}
Registry SiteConfig {
Key = 'HKLM:SOFTWAREMyApp'
ValueName = 'InstallPath'
ValueData = 'C:inetpubwwwrootapp'
ValueType = 'String'
Ensure = 'Present'
}
}
}
WebServerConfig -ComputerName 'WebServer01'
The DependsOn property ensures resources are applied in the correct order. In the example above, W3SVC and ASP.NET are only configured after the Web-Server feature is installed.
Compiling a Configuration to MOF
After writing the configuration script, you must compile it into a Managed Object Format (MOF) file. The MOF file is a platform-neutral representation of the configuration that the LCM can process. Running the configuration function compiles it:
. .WebServerConfig.ps1
WebServerConfig -ComputerName 'WebServer01' -OutputPath 'C:DSCMOF'
This produces a file at C:DSCMOFWebServer01.mof. Inspect the MOF to verify its contents:
Get-Content 'C:DSCMOFWebServer01.mof'
Each resource block in the MOF corresponds to a resource declaration in the configuration. When targeting multiple nodes, one MOF file is generated per node, named .mof.
Configuring the Local Configuration Manager
The Local Configuration Manager (LCM) is the DSC engine on each target node. It controls how configurations are applied, how often compliance is checked, and how drift is handled. The LCM is configured using a special DSC configuration block with the DscLocalConfigurationManager attribute:
[DscLocalConfigurationManager()]
Configuration LCMConfig {
Node 'WebServer01' {
Settings {
RefreshMode = 'Push'
ConfigurationMode = 'ApplyAndAutoCorrect'
RebootNodeIfNeeded = $true
ActionAfterReboot = 'ContinueConfiguration'
ConfigurationModeFrequencyMins = 30
}
}
}
LCMConfig -OutputPath 'C:DSCLCM'
Set-DscLocalConfigurationManager -Path 'C:DSCLCM' -Verbose
ConfigurationMode values: ApplyOnly (apply once, never re-check), ApplyAndMonitor (apply and report drift but don’t correct), ApplyAndAutoCorrect (apply and automatically remediate drift). ApplyAndAutoCorrect is the most commonly used mode for production servers where configuration consistency is mandatory.
Push Mode vs Pull Mode
DSC supports two delivery modes: Push and Pull.
Push mode is the simpler approach. The administrator manually calls Start-DscConfiguration from a management machine, which directly sends the MOF to the target node and instructs the LCM to apply it. Push mode is suitable for small environments or initial configuration. There is no automatic re-checking unless you configure the LCM’s ConfigurationModeFrequencyMins:
Start-DscConfiguration -Path 'C:DSCMOF' -ComputerName 'WebServer01' -Wait -Verbose -Force
Pull mode is designed for large-scale environments. Target nodes periodically contact a DSC Pull Server (or Azure Automation DSC) to check whether their configuration has changed. If a new version of the MOF is available, the node downloads and applies it automatically. Pull mode requires configuring the LCM with RefreshMode = ‘Pull’ and specifying the pull server URL. Nodes are identified by a ConfigurationID (GUID) or ConfigurationName. The pull server hosts MOF files and a checksum file for each configuration:
[DscLocalConfigurationManager()]
Configuration PullLCMConfig {
Node 'WebServer01' {
Settings {
RefreshMode = 'Pull'
ConfigurationMode = 'ApplyAndAutoCorrect'
RefreshFrequencyMins = 30
ConfigurationID = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
}
ConfigurationRepositoryWeb PullSrv {
ServerURL = 'https://dscpullserver.corp.local:8080/PSDSCPullServer.svc'
AllowUnsecureConnection = $false
}
}
}
Key Built-In DSC Resources
Windows Server 2022 includes several built-in DSC resources in the PSDesiredStateConfiguration module that cover the most common configuration tasks:
File — Manages files and directories. Supports creating, removing, and copying files; managing directory trees; setting file contents.
Service — Manages Windows services. Can ensure a service is running, stopped, or disabled with a specific startup type.
Registry — Manages registry keys and values. Supports all value types (String, DWord, QWord, Binary, MultiString, ExpandString).
WindowsFeature — Installs or removes Windows Server roles and features by their Name property (same names used with Install-WindowsFeature).
Environment — Manages system and user environment variables.
Group — Manages local security groups and their members.
User — Manages local user accounts.
Package — Installs or removes software packages from .msi or .exe installers.
Script — Runs arbitrary PowerShell scripts with GetScript, SetScript, and TestScript blocks for fully custom resources.
Applying a Configuration with Start-DscConfiguration
After compiling to MOF, apply the configuration using Start-DscConfiguration. The -Wait flag causes the cmdlet to block until the LCM finishes processing. The -Verbose flag shows detailed output for each resource:
Start-DscConfiguration -Path 'C:DSCMOF' -Wait -Verbose -Force
To apply to a remote computer:
Start-DscConfiguration -Path 'C:DSCMOF' -ComputerName 'WebServer01' -Wait -Verbose -Credential (Get-Credential)
Without -Wait, Start-DscConfiguration returns immediately and the LCM applies the configuration in the background. Use Get-DscConfigurationStatus to check the result.
Testing Configuration with Test-DscConfiguration
Before applying a configuration or to audit current compliance, use Test-DscConfiguration. This calls each resource’s Test method to check whether the current state matches the desired state without making any changes:
Test-DscConfiguration -Verbose
Returns True if all resources are in compliance, False if any resource is out of compliance. To get a detailed per-resource report:
Test-DscConfiguration -Detailed
The Detailed output includes ResourcesInDesiredState and ResourcesNotInDesiredState arrays, showing exactly which resources are drifted.
Troubleshooting DSC
DSC logs to the Windows Event Log under Microsoft-Windows-Desired State Configuration/Operational and Microsoft-Windows-Desired State Configuration/Analytic. Query DSC events with PowerShell:
Get-WinEvent -LogName 'Microsoft-Windows-Desired State Configuration/Operational' |
Select-Object TimeCreated, LevelDisplayName, Message |
Format-List
Enable the Analytic log for more verbose tracing (disabled by default):
wevtutil set-log "Microsoft-Windows-Desired State Configuration/Analytic" /enabled:true /quiet:true
Check the LCM’s current state and last configuration status:
Get-DscLocalConfigurationManager
Get the status of the most recent configuration run:
Get-DscConfigurationStatus
The Status property will be Success, Failure, or Pending. If a resource failed, the Error property contains the exception message. To view previously applied configurations:
Get-DscConfigurationStatus -All
For resource-level debugging, you can run a resource’s methods directly using Invoke-DscResource. This lets you test individual resources outside of a full configuration run:
Invoke-DscResource -Name WindowsFeature -Method Test -Property @{Name='Web-Server';Ensure='Present'} -ModuleName PSDesiredStateConfiguration