Build Custom Windows PowerShell Desired State Configuration Resources

Published: June 24, 2013

Updated: June 24, 2013

Applies To: Windows PowerShell 4.0

Windows PowerShell Desired State Configuration (DSC) has built-in resources that you can use to configure your environment. (For more information, see Built-In Windows PowerShell Desired State Configuration Resources.) This topic describes how you can extend this set of resources by creating custom resources. To create a custom DSC resource, you need a basic understanding of the following areas:

Requirements for creating a custom DSC resource

To implement a DSC custom resource, create the following folder structure, replacing ResourceName with the name you want to give to your custom resource. The three files that reside in the resource folder are explained in the sections that follow.

$env: psmodulepath (folder)
    |- <ModuleName> (folder)
        |- DSC Resources (folder)
            |- <ResourceName1> (folder)
                |- <ResourceName>.psd1 (file, optional)
                |- <ResourceName>.psm1 (file, required)
                |- <ResourceName>.schema.mof (file, required)
            |- <ResourceName2>(folder)
                |- <ResourceName2>.psd1 (file, optional)
                |- <ResourceName2>.psm1 (file, required)
                |- <ResourceName2>.schema.mof (file, required)

The following is a description of the three files that reside in the resource folder and form the resource.

MOF schema

The MOF schema defines the properties of the resource. To use your custom resource in a DSC configuration script, you assign values to these properties to indicate configuration options. Then save the MOF schema to a file called <ResourceName>.schema.mof.

You do not need to have prior experience with MOF files. If you are new to MOF, you can simply follow this example and modify it to match your needs. You can also create the script module that is described in the following section first, and then reverse-engineer the MOF schema based on that.

Following is an example MOF file that can be used for a custom website resource. To follow this example, save this schema to a file, and call the file Demo_IISWebsite.schema.mof.

[ClassVersion("1.0.0"), FriendlyName("Website")] 
class Demo_IISWebsite : OMI_BaseResource
  [Key] string Name;
  [write] string PhysicalPath;
  [write,ValueMap{"Present", "Absent"},Values{"Present", "Absent"}] string Ensure;
  [write,ValueMap{"Started","Stopped"},Values{"Started", "Stopped"}] string State;
  [write,ValueMap{"http", "https"},Values{"http", "https"}] string Protocol[];
  [write] string BindingInfo[];
  [write] string ApplicationPool;
  [read] string ID;

Note the following about the previous code:

  • FriendlyName defines the name you can use to refer to this custom resource in DSC configuration scripts. In this example, Website is equivalent to the friendly name Archive for the built-in Archive resource.

  • The class you define for your custom resource must derive from OMI_BaseResource.

  • The type qualifier, [Key], on a property indicates that this property will uniquely identify the resource instance.

  • The [write] qualifier indicates that you can assign a value to this property when using the custom resource in a configuration script. The [read] qualifier indicates that a property can only be read.

  • Values restricts the values that can be assigned to the property to the list of values defined in ValueMap. For more information, see ValueMap and Value Qualifiers.

  • Including a property called Ensure in your resource is recommended as a way to maintain a consistent style with built-in DSC resources.

  • Name the schema file for your custom resource as follows: classname.schema.mof, where classname is the identifier that follows the class keyword in your schema definition.

Script module

The script module implements the logic of the resource. In this module, you must include three functions called Get-TargetResource, Set-TargetResource, and Test-TargetResource. All three functions must take a parameter set that is identical to the set of properties defined in the MOF schema that you created for your resource. In this document, this set of properties is referred to as the “resource properties.” Store these three functions in a file called <ResourceName>.psm1. In the following example, the functions are stored in a file called Demo_IISWebsite.psm1.

When you run the same configuration script on your resource more than once, you should receive no errors and the resource should remain in the same state as running the script once. To accomplish this, ensure that your Get-TargetResource and Test-TargetResource functions leave the resource unchanged, and that invoking the Set-TargetResource function more than once in a sequence with the same parameter values is always equivalent to invoking it once.

In the Get-TargetResource function implementation, use the key resource property values that are provided as parameters to check the status of the specified resource instance. This function must return a hash table that lists all the resource properties as keys and the actual values of these properties as the corresponding values. The following code provides an example.

# DSC uses the Get-TargetResource function to fetch the status of the resource instance specified in the parameters for the target machine
function Get-TargetResource 
        [ValidateSet("Present", "Absent")]
        [string]$Ensure = "Present",



        [ValidateSet("Started", "Stopped")]
        [string]$State = "Started",




        $getTargetResourceResult = $null;

        <# Insert logic that uses the mandatory parameter values to get the website and assign it to a variable called $Website #>
        <# Set $ensureResult to "Present" if the requested website exists and to "Absent" otherwise #>

        # Add all Website properties to the hash table
        # This simple example assumes that $Website is not null
        $getTargetResourceResult = @{
                                      Name = $Website.Name; 
                                        Ensure = $ensureResult;
                                        PhysicalPath = $Website.physicalPath;
                                        State = $Website.state;
                                        ID = $;
                                        ApplicationPool = $Website.applicationPool;
                                        Protocol = $Website.bindings.Collection.protocol;
                                        Binding = $Website.bindings.Collection.bindingInformation;

Depending on the values that are specified for the resource properties in the configuration script, the Set-Target resource must do one of the following:

  • Create a new website

  • Update an existing website

  • Delete an existing website

The following example illustrates this.

# The Set-TargetResource function is used to create, delete or configure a website on the target machine. 
function Set-TargetResource 
        [ValidateSet("Present", "Absent")]
        [string]$Ensure = "Present",



        [ValidateSet("Started", "Stopped")]
        [string]$State = "Started",



    <# If Ensure is set to "Present" and the website specified in the mandatory input parameters does not exist, then create it using the specified parameter values #>
    <# Else, if Ensure is set to "Present" and the website does exist, then update its properties to match the values provided in the non-mandatory parameter values #>
    <# Else, if Ensure is set to "Absent" and the website does not exist, then do nothing #>
    <# Else, if Ensure is set to "Absent" and the website does exist, then delete the website #>

Finally, the Test-TargetResource function must take the same parameter set as Get-TargetResource and Set-TargetResource. In your implementation of Test-TargetResource, check the status of the resource instance that is specified in the key parameters. If the actual status of the resource instance does not match the values specified in the parameter set, return $false. Otherwise, return $true.

For easier debugging, use the Write-Verbose cmdlet in your implementation of the previous three functions. This cmdlet writes text to the verbose message stream. By default, the verbose message stream is not displayed, but you can display it by changing the value of the $VerbosePreference variable or by using the Verbose parameter in the DSC cmdlets.

Module manifest

Finally, use the New-ModuleManifest cmdlet to define a <ResourceName>.psd1 file for your custom resource module. When you invoke this cmdlet, reference the script module (.psm1) file described in the previous section. Include Get-TargetResource, Set-TargetResource, and Test-TargetResource in the list of functions to export. Following is an example manifest file.

# Module manifest for module 'Demo.IIS.Website'
# Generated on: 1/10/2013


# Script module or binary module file associated with this manifest.
# RootModule = ''

# Version number of this module.
ModuleVersion = '1.0'

# ID used to uniquely identify this module
GUID = '6AB5ED33-E923-41d8-A3A4-5ADDA2B301DE'

# Author of this module
Author = 'Contoso'

# Company or vendor of this module
CompanyName = 'Contoso'

# Copyright statement for this module
Copyright = 'Contoso. All rights reserved.'

# Description of the functionality provided by this module
Description = 'This Module is used to support the creation and configuration of IIS Websites through Get, Set and Test API on the DSC managed nodes.'

# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '4.0'

# Minimum version of the common language runtime (CLR) required by this module
CLRVersion = '4.0'

# Modules that must be imported into the global environment prior to importing this module
RequiredModules = @("WebAdministration")

# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
NestedModules = @("Demo_IISWebsite.psm1")

# Functions to export from this module
FunctionsToExport = @("Get-TargetResource", "Set-TargetResource", "Test-TargetResource")

# Cmdlets to export from this module
#CmdletsToExport = '*'

# HelpInfo URI of this module
# HelpInfoURI = ''

Community Additions

© 2014 Microsoft