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.