Windows PowerShell Desired State Configuration (DSC) is a great way to keep all of your Windows server configurations in check. DSC provides an easy way to simply define what you'd like your server to look like, then let DSC do the rest. To support this functionality, DSC has a concept called a resource.

A resource is a way in which you can write code to instruct DSC to perform actions on various components of the operating system. There are many built-in resources such as File, Registry, WindowsFeature, and so on. For a full list, you can run Get-DscResource to find out.

Even though DSC provides many out-of-the-box resources, there are times when these resources are not enough. When you run into a situation where you need to configure something that doesn't have a built-in DSC resource, you have the option to build your own. Doing this has historically meant building MOF-based resources. Introduced as part of the first DSC iteration back in PowerShell v4, MOF-based resources required too many steps, and building them wasn’t very intuitive.

However, as of PowerShell v5, we now have support for classes, and as a result, we can now also develop resources via classes instead of having to create MOF files. In this article, let's go over how to build your first DSC class-based resource in PowerShell.

For this demonstration, I'm going to create a DSC resource called MyFolder (using PowerShell v5, obviously). I'll be using PowerShell v5 RTM, but if you're working any of the previous v5 builds, they should work as well. MyFolder is a super simple resource that checks whether a folder exists or not. You could use the built-in File resource for this, but just to keep it simple, we'll build our own.

In reality, a DSC resource is simply a PowerShell module, so we'll first need to ensure that a folder with the same name as our resource is in one of the paths in $env:PSModulePath.

$moduleFolder = "$env:ProgramFiles\WindowsPowerShell\Modules\MyFolder"
mkdir $moduleFolder

Next, we need to build a module with a manifest New-ModuleManifest (or however you prefer). At a minimum, you'll need to use the DSCResourcesToExport parameter and the RootModule parameter.

New-ModuleManifest -DscResourcesToExport 'MyFolder' -RootModule 'MyFolder.psm1' -Path "$moduleFolder\MyModule.psd1"

Now you'll build the module itself and save it to "$moduleFolder\MyModule.psm1" when you're done.

The module will consist of two main sections: the enumerator and the DSC resource itself. An enumerator is required to define the state of the system. In this example, I'm choosing to use “Absent” or “Present” labels. However, you can use any kind of labels you'd like.

enum Ensure
 {
     Present
     Absent
 }

Next, we define the resource, as outlined below.

[DscResource()]
 class MyFolder ## MyFolder is the name of the resource
 {
     [DscProperty(Key)] ## The Key property is required to uniquely identify the resource
     [string]$Path
     
     [DscProperty(Mandatory)] ## At least one mandatory property is required
     [Ensure]$Ensure
     
 ## What to do if it's not in the right state. This returns nothing, indicated by [void].
     [void] Set() 
     {
         
     }
     ## Test to ensure it's in the right state. This returns a Boolean value, indicated by [bool].
     [bool] Test() 
     {
         
     }
     ## Get the state. This returns an instance of the class itself, indicated by [MyFolder]
     [MyFolder] Get() 
     {
         
     }
 }

When this resource is run, it will first run the Get() method. This retrieves the current state of the resource. Our Get() method looks like this:

[MyFolder] Get()
{
    if (Test-Path -Path $this.Path)
    {
        $this.Ensure = [Ensure]::Present
    }
    else
    {
        $this.Ensure = [Ensure]::Absent
    }
    return $this
}

It's testing -Path parameter to ensure that the folder path exists . If it exists, it sets our enumerator to Present. If not, our enumerator is set to Absent. Finally (and more importantly) it returns a MyFolder class instance when finished.

Next, DSC will run the Test() method. This will return a $true or $false value depending on if the system is in the desired state (as defined by what we pass into the $Ensure parameter later).

[bool] Test()
 {
     $There = Test-Path -Path $this.Path
     if ($this.Ensure -eq [Ensure]::Present)
     {
         return $There
     }
     else
     {
         return -not $There
     }
 }

You can see that it's testing to see if the folder exists. If it does, it sets the Ensure property of our MyFolder object to $true. If not, it's the opposite (if we actually want to remove the folder).

Finally, we have the Set() method—what actually does the work if Test returned a $false value.

[void] Set()
 {
     if ($this.Ensure -eq [Ensure]::Present)
     {
         $null = mkdir $this.Path
     }
     elseif ($this.Ensure -eq [Ensure]::Absent)
     {
         Remove-Item -Path $this.Path -Force
     }
 }

Save your PSM1 file. We're done.

Finally, we need to kick it off. To do this, we'll build a configuration—you can call it whatever you like. Here, I'm choosing MyFolderConfig. I'm importing the DSC resource that we just created, defining the MyFolder resource, and calling it DoIt with the parameters we defined for that class.

Configuration MyFolderConfig
 {
     Import-DSCResource -module MyFolder
     MyFolder DoIt
     {
         Path = 'C:\SomeDirectory'
         Ensure = 'Present'
     }
 }

Once I have this loaded into my session, I can call it just like I would a function.

MyFolderConfig

This will create a MOF file MyFolderConfig on my local system. Then, it's just a matter of starting the DSC configuration process referencing that MOF file we just created!

Subscribe to 4sysops newsletter!

Start-DscConfiguration -Wait -Force MyFolderConfig –Verbose

This will consume the MOF file, wait until the process is done and give you verbose output to get a glimpse into what's happening.

2 Comments
  1. Bjørn Roalkvam 7 years ago

    Hi Adam,

    Thank you for this clear and easy to understand overview on how to make dscresources using the PowerShell 5 classes! Im about to write my first powershell 5 class dsc resource now!

    brgs

    Bjørn

  2. Sam 7 years ago

    I’m trying to follow your sample but getting exception while testing it i.e. compiling the configuration.

    Import-DSCResource -module MyFolder

    Could not find the module ‘MyFolder’.

    At line:4 char:6

    +      MyFolder DoIt

     

    Thanks for your help

Leave a reply

Your email address will not be published.

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account