Introduction to Desired State Configuration (DSC)
PowerShell Intermediate/Advanced
Chapter 9 · Introduction to Desired State Configuration (DSC)
Every script written since Fundamentals 7 has been imperative: a sequence of steps, executed once, that you're responsible for making safe to re-run yourself — exactly the discipline the Fundamentals capstone's own try/catch-wrapped Remove-Item was built around. DSC is a genuine departure from that whole model: instead of writing steps, you declare the end state you want, and let DSC's own engine figure out — and keep checking — whether reality matches it.
The Configuration Keyword & Resources
Configuration is its own distinct keyword, not a function — inside it, Node blocks target specific machines, and inside those, each named block (WindowsFeature, Service, File, Registry, and more) is a resource declaring a piece of desired state, almost always including an Ensure = "Present"/"Absent" property. DependsOn makes ordering explicit where it genuinely matters — here, IIS has to actually be installed before its own W3SVC service can be started.
Compiling a Configuration: .mof Files
Writing the block above doesn't apply anything by itself — Configuration defines a template that has to be compiled first, by calling it like a function:
A .mof (Managed Object Format) file is the actual, portable artifact DSC works from — a real, easy-to-miss two-step process: define the configuration, then compile it, and only after that, apply it.
Applying It: Start-DscConfiguration
Only this step actually does anything to the target machine — checking each resource's current state and taking action only where it doesn't already match.
The Real Payoff: Idempotency, Built In
Start-DscConfiguration a second time against a node that's already fully compliant, and nothing happens — no error, no duplicate install, no second attempt to start an already-running service. This isn't something you had to code yourself the way the Fundamentals capstone's own Remove-Item needed an explicit try/catch and careful "does this still exist" thinking — every DSC resource builds a "check the current state, only act if it's actually different" test into itself as a fundamental design principle. Declarative configuration means idempotency is the resource's own job, not yours.
Detecting and Correcting Drift
Test-DscConfiguration answers "has anything drifted?" without touching anything — a service someone stopped manually, a file someone edited by hand. A node's Local Configuration Manager (LCM) can even be set to periodically re-check and auto-correct drift on its own, turning a one-time configuration into an ongoing, self-healing guarantee — the real distinguishing value DSC has over a script that only ever runs once.
The Escape Hatch: The Script Resource
For anything not covered by a built-in resource, Script lets you hand-write the three pieces DSC's own idempotency model needs: TestScript (is this already true?), SetScript (make it true, only called if TestScript says no), and GetScript (report the current state) — the same idempotent-by-design contract every built-in resource already follows, just written by hand.
Script resource, check whether a built-in resource already covers what you need — WindowsFeature, Service, File, and Registry alone cover a large share of real configuration tasks, already idempotent, with no hand-written TestScript logic to get right yourself.
Hands-On Exercises
Explain the core difference between a DSC Configuration block and an ordinary PowerShell function, using this chapter's own declarative-vs-imperative framing.
Explain what actually happens when you call MyWebServerConfig -OutputPath .\MyWebServerConfig. What gets produced, and what hasn't happened yet at that point?
Explain why running Start-DscConfiguration a second time against an already-compliant node does nothing, contrasting this directly with how the Fundamentals capstone had to manually check state before calling Remove-Item.
Chapter 9 Quick Reference
- Declarative, not imperative — describe the desired end state; DSC's engine figures out how to get there
Configuration/Node/ resources — a distinct keyword;Nodetargets a machine; each resource block (WindowsFeature,Service,File,Registry) declares one piece of desired state- Compiling — calling the configuration like a function produces a
.moffile per node; nothing is applied yet at this step Start-DscConfiguration— the step that actually checks and applies state- Idempotency is built into the resource — re-running against a compliant node does nothing; you never hand-code the "does this already exist" check yourself
Test-DscConfiguration— checks for drift without applying anythingScriptresource — the escape hatch;TestScript/SetScript/GetScriptreproduce the same idempotent contract by hand- Honest scope note: class-based resources, pull servers, Azure Automation DSC, and DSC v3 are all genuinely beyond this introduction
- Next chapter: Testing PowerShell Code with Pester