Creating DSC Resource Snippets for the PowerShell ISE

Without a doubt creating configurations for Desired State Configuration (DSC) in PowerShell 4.0 is one of the hottest topics in the PowerShell world these days. But as is often the case with new technologies, discovering what to use can be a challenge. Fortunately for PowerShell and DSC this does not have to be difficult task.

Using the Get-DSCResource cmdlet

In a DSC configuration you need to define resources for the managed nodes. You can use the Get-DSCResource cmdlet to discover resources installed locally. Even though you will be creating configurations for servers, you will most likely be using the PowerShell ISE on a Windows 8.1client. Given that you will most likely have the same DSC resource modules installed locally.
One of the reasons for this is so that you can discover the resource syntax. The Get-DSCResource cmdlet can either display information about a resource or provide its syntax. Let’s say you are creating a configuration that will use the xSMBShare resource. You can see the syntax like this:

Get-DscResource xsmbshare -Syntax

Creating DSC Resource Snippets for the PowerShell ISE
You can then copy and paste this into the ISE. Or copy it directly to the clipboard.

Get-DscResource xsmbshare –Syntax | clip

Another option is to use a function in the ISE to get the syntax and paste it into the current document.

Function Insert-DSCSyntax {
Param([string]$Name)
Try {
[string]$syntax = Get-DscResource -Name $Name -Syntax
#insert into current document at current location
$psise.CurrentFile.Editor.InsertText($syntax)
}
Catch {
throw
}
}

Run the function specifying a resource name and the syntax will be pasted into the current file. Or how about this? Use Out-GridView as an object picker for the resources you want to use?

Get-DscResource | Select Name,Module |
Out-GridView -title "Select some resources" -OutputMode Multiple |
Foreach {
 Insert-DSCSyntax $_.Name
}

102214 1817 CreatingDSC3
When I click OK the syntax for the selected resources will be inserted into my current file. This will run much faster in PowerShell 5.0 but gets the job done. All I need to do is edit each entry. But I have an approach I like even better. Why not turn each resource syntax into an ISE snippet?

With an ISE Snippet you press Ctrl+J, find the snippet, press Enter and the text is inserted into the current file. My initial thought was to use the Syntax string with the New-ISESnippet cmdlet. But then I’d have to mess around with parsing the output to find something to use for a title. So instead, I came up with this function.

#requires -version 4.0
Function New-DSCResourceSnippet {
<#
.Synopsis
Create ISE snippets for DSC Resources
.Description
This command will convert the syntax for a DSC resource into an ISE snippet. Snippets will be created in the default location. Snippet names will take the name "DSC <resource name>". The snippet description uses the format "<Resource Name> resource from module <module name> <vendor>". You will end up with a description like this:
xWinEventLog resource from module xWinEventLog Microsoft Corporation
You must run this command in the PowerShell ISE.
.Example
PS C:\> New-DSCResourceSnippet -name xsmbshare -author "Jeff Hicks" -passthru
    Directory: C:\Users\Jeff\documents\WindowsPowerShell\Snippets
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        10/20/2014   8:48 AM       1157 DSC xSmbShare Resource.snippets.ps1xml
Create a snippet from a single resource.
.Example
PS C:\> Get-DSCResource | New-DSCResourceSnippet
This command will create snippets for every installed DSC resource. Existing snippet files will be overwritten.
.Notes
Last Updated: October 20, 2014
Version     : 1.0
Learn more about PowerShell:
Essential PowerShell Learning Resources
**************************************************************** * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED * * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF * * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, * * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. * **************************************************************** .Link Get-DSCResource New-ISESnippet #> [cmdletbinding(SupportsShouldProcess=$True,DefaultParameterSetName="Name")] Param( [Parameter(Position=0,Mandatory=$True,HelpMessage="Enter the name of a DSC resource", ParameterSetName="Name")] [ValidateNotNullorEmpty()] [string[]]$Name, [Parameter(Position=0,Mandatory=$True,HelpMessage="Enter the name of a DSC resource", ValueFromPipeline=$True,ParameterSetName="Resource")] [ValidateNotNullorEmpty()] [Microsoft.PowerShell.DesiredStateConfiguration.DscResourceInfo[]] $DSCResource, [ValidateNotNullorEmpty()] [string]$Author = $env:username, [Switch]$Passthru ) Begin { Write-Verbose -Message "Starting $($MyInvocation.Mycommand)" } #begin Process { if ($PSCmdlet.ParameterSetName -eq 'Name') { #get the resource from the name Try { Write-Verbose "Getting DSC Resource $Name" $DSCResource = Get-DscResource -Name $Name -ErrorAction Stop } Catch { Throw } } foreach ($resource in $DSCResource) { #create the entry based on resource properties [string[]]$entry = "`n$($resource.name) <ResourceID> {`n" Write-Verbose "Creating resource entry for $($resource.name)" $entry+= "`t#from module $($resource.module.name)" $entry+= foreach ($item in $resource.Properties) { if ($item.IsMandatory) { $resourcename="`t*$($item.name)" } else { $resourcename = "`t$($item.name)" } if ($item.PropertyType -eq '[bool]') { $possibleValues = "`$True | `$False" } elseif ($item.values) { $possibleValues = "'$($item.Values -join "' | '")'" } else { $possibleValues=$item.PropertyType } "$resourcename = $($possibleValues)" } #foreach $entry+="`n} #end $($resource.name) resource`n`n" $title = "DSC $($resource.name) Resource" $description = "$($resource.name) resource from module $($resource.module) $($resource.CompanyName)" Write-Verbose "Creating snippet $title" Write-Verbose $description Write-Verbose ($entry | out-string) $paramHash = @{ Title = $Title Description = $description Text = ($Entry | Out-String) Author = $Author Force = $True ErrorAction = "Stop" } Write-Verbose ($paramHash | out-string) if ($PSCmdlet.ShouldProcess($Resource.name)) { Try { Write-Debug "Creating snippet file" New-IseSnippet @paramHash if ($Passthru) { #build the path $snippath = join-path -path "$env:Userprofile\documents\WindowsPowerShell\Snippets" -ChildPath "$title.snippets.ps1xml" Get-Item -path $snippath } } Catch { Throw } } #if shouldprocess } #foreach resource } #process End { #import the new snippets into the current session. They will #automatically be loaded next time. Write-Verbose "Importing new snippets" Import-IseSnippet -Path "$env:Userprofile\documents\WindowsPowerShell\Snippets" Write-Verbose -Message "Ending $($MyInvocation.Mycommand)" } #end } #end function

This is something you really only need to run once and it must be done from the PowerShell ISE. Or you can re-run it if you install new or updated resource modules. The function takes the name of a resource and constructs the syntax from the resource properties. Mandatory properties will be indicated with a *. The function will create a snippet file in the default user location using the resource name as the title. The module and vendor name will be included in the description. You can use it to create a single snippet.

New-DSCResourceSnippet -name xsmbshare -author "Jeff Hicks" –passthru

Or create snippets for everything.

Get-DSCResource | New-DSCResourceSnippet


The function will automatically import them into your current ISE session so you can use them immediately. The next time you start the ISE they should automatically be available. Once run, you can easily insert new resources.
102214 1817 CreatingDSC4
All of the snippets will start with DSC. Once inserted, edit as necessary. With this, creating configurations for DSC is much, much easier and faster. The function has full help and examples. I definitely hope you’ll try this out and let me know what you think.