Home Technology Killer Feature in PSv4: Desired State Configuration

Killer Feature in PSv4: Desired State Configuration

Most of the things found in PowerShell 4.0 is consolidation work, but there is one feature called Desired State Configuration (DSC) that really has the potential to become a killer feature.

Desired State Configuration (DSC)

DSC is a new way of configuring local and remote machines. Instead of writing a lot of script code, you can use the new configuration keyword which works very similar to a PowerShell function.

The actual work is done inside of it, using DSC?resources called “group“, “service“, or “registry“, for example. A full list of resources shipped with DSC can be found here.

Each resource is technically represented by a DSC provider you can go and visit:

explorer $pshome\Modules\PSDesiredStateConfiguration\PSProviders

Note: Inside of each provider folder, which really turns out to be a PowerShell module, ?you find an en-US subfolder with the resources. If you want to test-drive DSC on a non-US system, you will have to copy the en-US folder in each of the provider folders and rename it to the locale you use.

These resources “know” how to do the actual configuration work, so you just need to let the resource know what you want it to do, i.e. let the registry resource know what registry key and value you want to manipulate.

The resources then can do three things: they can test whether the configuration is in place, they can make sure the configuration is done, and they can also revert (remove) the configuration.

Here is a piece of sample code that defines some configuration tasks:

Configuration MyTestConfig

    Node $MachineName
        Group TestGroup
            Ensure ="Present"

        Service WinUpdate
            Name ="wuauserv"

        Script ScriptExample
                $sw=New-Object System.IO.StreamWriter("$env:temp\TestFile.txt")
                $sw.WriteLine("Some sample string")
            TestScript ={Test-Path "C:\TempFolder\TestFile.txt"}
            GetScript={ <# This must return a hash table #>}

        Registry RegistryExample
            Ensure ="Present" # You can also set Ensure to "Absent"
            Key ="HKEY_LOCAL_MACHINE\SOFTWARE\ExampleKey"

        Environment EnvironmentExample
            Ensure ="Present" # You can also set Ensure to "Absent"
            Name ="TestEnvironmentVariable"
            Value ="TestValue"

Turning a Configuration into a MOF file

The actual configuration is not done by your script. Instead, your script takes the configuration data (your parameters) and turns it into a MOF file. Here are two lines of code that illustrate how you’d turn the above configuration into a MOF file:

$null = md C:\dscconfig -ErrorAction SilentlyContinue
MyTestConfig -MachineName $env:COMPUTERNAME -OutputPath c:\dscconfig

The MOF file would look similar to this:

@GenerationDate=06/27/2013 22:29:38

instance of MSFT_GroupResource as $MSFT_GroupResource1ref
ResourceID = "[Group]TestGroup";
 Ensure = "Present";
 GroupName = "TestGroup";
 SourceInfo = "::9::9::Group";
 ModuleName = "MSFT_GroupResource";
 ModuleVersion = "1.0";
 Requires = {


instance of MSFT_ServiceResource as $MSFT_ServiceResource1ref
ResourceID = "[Service]WinUpdate";
 SourceInfo = "::15::9::Service";
 Name = "wuauserv";
 StartupType = "Automatic";
 ModuleName = "MSFT_ServiceResource";
 ModuleVersion = "1.0";
 Requires = {


instance of MSFT_ScriptResource as $MSFT_ScriptResource1ref
ResourceID = "[Script]ScriptExample";
 GetScript = " <# This must return a hash table #>";
 TestScript = "Test-Path \"C:\\TempFolder\\TestFile.txt\"";
 SourceInfo = "::21::9::Script";
 SetScript = "\n                $sw=New-Object System.IO.StreamWriter(\"$env:temp\\TestFile.txt\")\n                $sw.WriteLine(\"Some sample string\")\n                $sw.Close()\n            ";
 ModuleName = "MSFT_ScriptResource";
 ModuleVersion = "1.0";
 Requires = {


instance of MSFT_RegistryResource as $MSFT_RegistryResource1ref
ResourceID = "[Registry]RegistryExample";
 ValueName = "TestValue";
 Ensure = "Present";
 SourceInfo = "::32::9::Registry";
 ModuleName = "MSFT_RegistryResource";
 ValueData = {
 ModuleVersion = "1.0";
 Requires = {


instance of MSFT_EnvironmentResource as $MSFT_EnvironmentResource1ref
ResourceID = "[Environment]EnvironmentExample";
 Ensure = "Present";
 Value = "TestValue";
 SourceInfo = "::40::9::Environment";
 Name = "TestEnvironmentVariable";
 ModuleName = "MSFT_EnvironmentResource";
 ModuleVersion = "1.0";
 Requires = {


instance of OMI_ConfigurationDocument
 GenerationDate="06/27/2013 22:29:38";

The MOF file then can be applied to a machine:

Start-DscConfiguration -Wait -Path c:\dscconfig

Note the -Wait parameter: by default, the configuration task runs in the background.

With -Wait, you turn this into an interactive process which can be useful to watch the configuration take place and see any exceptions raised.

Currently, PowerShell 4.0 preview runs on all locales, for example, but the DSC modules only ship with en-US resources.

So when you try this code on a non-US machine, you get exceptions complaining about missing resources. As a workaround, you can manually copy the en-US resources inside of the DSC modules and rename them to whatever locale you use (like mentioned above when you were visiting the resources).

Applying Configurations to Remote Machines

Of course you can also apply a MOF file to a remote machine, provided you created the MOF file for this machine (i.e., in the example above used -MachineName when you called your configuration to create the MOF file and submitted the appropriate target computer name, or created your own configuration script and added appropriately named nodes manually).

Always remember, though, that the MOF file just contains the configuration parameters (what you want to be done). The actual implementation (how what you want is put into reality) is done by PowerShell modules that are part of the DSC (we’ll look at them in a second).

Which is why currently, the target machine must also have PowerShell 4.0 (WMF 4.0) installed.

How DSC really works

In a nutshell, when you run your configuration script, a MOF file for each node is generated (one MOF file for each target computer you specify). It encapsulates the parameters for the DSC resources you used.

A MOF file can then be applied by running Start-DSCConfiguration. This invokes the DSC engine?on the target side.

The actual work is done by the DSC resources which really are PowerShell modules. So if your configuration was to unzip a ZIP archive, your configuration would use the Archive resource which corresponds to the module MSFT_ArchiveResource:

explorer C:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfiguration\PSProviders\MSFT_ArchiveResource

DSC Resources are really PowerShell Modules

As you just saw, each DSC resource really is tied to a corresponding PowerShell module. These modules all at minimum implement three functions in its *.psm1 file:

  • Test-TargetResource: determines whether the configuration is in the desired state. It is used by the DSC engine to evaluate what it needs to do
  • Set-TargetResource: implements the configuration. This function must both implement Ensure=Present and Ensure=Absent, so it needs to be able to apply the configuration or remove it.
  • Get-TargetResource: inventories the resource based on its mandatory parameters and returns a hashtable.

The existing DSC providers are a highly interesting resource. They not only illustrate how DSC providers work (and could be extended by your own).

Since the modules are plain PowerShell code, you can also have a close look and find out how the providers do their job, i.e. how they create and remove local groups and users, or how they unpack a ZIP archive.

MOF Schema File Needed

A DSC provider also needs a so-called MOF schema file. This file defines the configuration data and how it is to be serialized and interpreted. In the case of the Archive provider, it looks like this:
[ClassVersion("1.0.0"), FriendlyName("Archive")] 
class MSFT_ArchiveResource : OMI_BaseResource
  [write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure;
  [Key] string Path;
  [Key] string Destination;
  [write] boolean Validate;
  [write,ValueMap{"SHA-1", "SHA-256", "SHA-512", "CreatedDate", "ModifiedDate"},Values{"SHA-1", "SHA-256", "SHA-512", "CreatedDate", "ModifiedDate"}] string Checksum;
  [write] boolean Force;

So basically, the schema file defines the properties that can be configured by the user inside of his or her configuration script.

Extending DSC

DSC obviously is pretty new to all of us, and a lot of people are experimenting with it. One interesting project investigates ways to?extend the DSC configuration resources. Here, you also find a lot of interesting background information on DSC and how it works behind the scenes.

That’s it for today,
a great week to all of you!

MVP PowerShell

For high quality PowerShell trainings in Europe, contact me at [email protected].

We do public trainings, Inhouse Workshops, tailored to your need: Beginners Classes, Advanced Courses, Special Topics like Active Directory, Exchange, Lync, SharePoint, Virtualization, and also Accelerated Classes to move experienced VBScripters over to PowerShell.

Primary language is German, but we also offer classes in English, Spanish, French and Italian.

Of course, we also provide consultant services for projects involving PowerShell.