27

我在尝试让 PowerShell Desired State Configuration 脚本工作来配置内部应用程序时遇到了很多麻烦。问题的根源是我似乎无法将我的配置数据传递到 ScriptResource 中(至少不是我尝试这样做的方式)。

我的脚本应该为我们的内部应用程序创建一个配置文件夹,然后将一些设置写入文件:

configuration MyApp {
    param (
        [string[]] $ComputerName = $env:ComputerName
    )
    node $ComputerName {

        File ConfigurationFolder {
            Type = "Directory"
            DestinationPath = $Node.ConfigFolder
            Ensure = "Present"
        }

        Script ConfigurationFile {
            SetScript = {
                write-verbose "running ConfigurationFile.SetScript";
                write-verbose "folder = $($Node.ConfigFolder)";
                write-verbose "filename = $($Node.ConfigFile)";
                [System.IO.File]::WriteAllText($Node.ConfigFile, "enabled=" + $Node.Enabled);
            }
            TestScript = {
                write-verbose "running ConfigurationFile.TestScript";
                write-verbose "folder = $($Node.ConfigFolder)";
                write-verbose "filename = $($Node.ConfigFile)";
                return (Test-Path $Node.ConfigFile);
            }
            GetScript = { @{Configured = (Test-Path $Node.ConfigFile)} }         
            DependsOn = "[File]ConfigurationFolder"
        }

    }
}

作为参考,我的配置数据如下所示:

$config = @{
    AllNodes = @(
        @{
            NodeName = "*"
            ConfigFolder = "C:\myapp\config"
            ConfigFile = "C:\myapp\config\config.txt"
        }
        @{
            NodeName = "ServerA"
            Enabled = "true"
        }
        @{
            NodeName = "ServerB"
            Enabled = "false"
        }
    )
}

我正在使用以下内容应用 DSC:

$mof = MyApp -ConfigurationData $config;
Start-DscConfiguration MyApp –Wait –Verbose;

当我应用此配置时,它会愉快地创建文件夹,但无法对配置文件执行任何操作。查看下面的输出,很明显这是因为 $Node 变量在 ConfigurationFile / TestScript 范围内为空,但我不知道如何从该块中引用它。

LCM:  [ Start  Resource ]  [[Script]ConfigurationFile]
LCM:  [ Start  Test     ]  [[Script]ConfigurationFile]
                           [[Script]ConfigurationFile] running ConfigurationFile.TestScript
                           [[Script]ConfigurationFile] node is null = True
                           [[Script]ConfigurationFile] folder =
                           [[Script]ConfigurationFile] filename =
LCM:  [ End    Test     ]  [[Script]ConfigurationFile]  in 0.4850 seconds.

我花了一整天的时间在线搜索这个特定问题,但是所有变量、参数和配置数据的示例都使用文件和注册表资源或其他非脚本资源,我已经在“ConfigurationFolder “在我的脚本中阻止。我坚持的事情是如何从脚本资源中引用配置数据,比如我的“ConfigurationFile”。

我已经画了一个完整的空白,所以任何帮助将不胜感激。如果一切都失败了,我可能必须为每个服务器创建一个单独的“配置”脚本并对值进行硬编码,如果可能的话,我真的不想这样做。

干杯,

麦克风

4

4 回答 4

36

将其更改$Node.ConfigFolder$using:Node.ConfigFolder.

如果您有一个名为的变量$Foo,并且您希望将其传递给脚本 DSC 资源,则使用$using:Foo

于 2015-01-08T19:27:14.783 回答
10

根据 David 的回答,我编写了一个实用函数,它将我的脚本块转换为字符串,然后执行非常简单的搜索和替换以扩展对配置数据的引用,如下所示。

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;
}

我的 SetScript 然后变成:

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);
            }

您必须注意配置数据中的引号和转义符,因为 Format-DscScriptBlock 仅执行文字替换,但这对于我的目的来说已经足够了。

于 2014-05-06T07:52:40.993 回答
8

解决此问题的一种非常优雅的方法是使用常规{0}占位符。通过应用-f运算符,占位符可以替换为它们的实际值。

这种方法的唯一缺点是您不能将大括号 { } 用于除占位符(即哈希表或 for 循环)以外的任何内容,因为-f运算符要求大括号包含整数。

您的代码如下所示:

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

此外,确定您是否正确执行此操作的一个好方法是使用文本编辑器查看生成的 .mof 文件;如果您查看生成的 TestScript / GetScript / SetScript 成员,您会发现代码片段确实是一个字符串。$placeholder 值应该已经在那里被替换了。

于 2014-11-26T18:34:01.557 回答
7

ConfigurationData 仅在编译 MOF 文件时存在,而不是在 DSC 引擎应用您的脚本时的运行时存在。Script 资源的 SetScript、GetScript 和 TestScript 属性实际上是字符串,而不是脚本块。

可以生成这些脚本字符串(您的 ConfigurationData 中的所有必需数据都已展开),但您必须小心正确使用转义、子表达式和引号。

我在http://social.technet.microsoft.com/Forums/en-US/2eb97d67-f1fb-4857-8840-de9c4cb9cae0/dsc-configuration-data-for-的原始 TechNet 线程上发布了一个简短示例脚本资源?论坛=winserverpowershell

于 2014-05-05T03:52:29.250 回答