PowerShell DSC - how to pass configuration parameters to ScriptResources? PowerShell DSC - how to pass configuration parameters to ScriptResources? powershell powershell

PowerShell DSC - how to pass configuration parameters to ScriptResources?


Change this: $Node.ConfigFolder to $using:Node.ConfigFolder.

If you have a variable called $Foo and you want it to be passed to a script DSC resource, then use $using:Foo


Based on David's answer, I've written a utility function which converts my script block to a string and then performs a very naive search and replace to expand out references to the configuration data as follows.

function Format-DscScriptBlock(){    param(        [parameter(Mandatory=$true)]        [System.Collections.Hashtable] $node,        [parameter(Mandatory=$true)]        [System.Management.Automation.ScriptBlock] $scriptBlock    )    $result = $scriptBlock.ToString();    foreach( $key in $node.Keys )    {        $result = $result.Replace("`$Node.$key", $node[$key]);    }    return $result;}

My SetScript then becomes:

SetScript = Format-DscScriptBlock -Node $Node -ScriptBlock {                write-verbose "running ConfigurationFile.SetScript";                write-verbose "folder = $Node.ConfigFolder";                write-verbose "filename = $Node.ConfigFile)";                [System.IO.File]::WriteAllText("$Node.ConfigFile", "enabled=" + $Node.Enabled);            }

You have to be mindful of quotes and escapes in your configuration data because Format-DscScriptBlock only performs literal substitution, but this was good enough for my purposes.


A quite elegant way to solve this problem is to work with the regular {0} placeholders. By applying the -f operator the placeholders can be replaced with their actual values.

The only downside with this method is that you cannot use the curly braces { } for anything other than placeholders (i.e. say a hashtable or a for-loop), because the -f operator requires the braces to contain an integer.

Your code then looks like this:

        SetScript = ({             Set-ItemProperty "IIS:\AppPools\{0}" "managedRuntimeVersion" "v4.0"            Set-ItemProperty "IIS:\AppPools\{0}" "managedPipelineMode" 1 # 0 = Integrated, 1 = Classic        } -f @($ApplicationPoolName))

Also, a good way to find out if you're doing it right is by simply viewing the generated .mof file with a text editor; if you look at the generated TestScript / GetScript / SetScript members, you'll see that the code fragment really is a string. The $placeholder values should already have been replaced there.