Desired State Configuration 无法从脚本资源获取块获取哈希表

Ben*_*rce 0 powershell hashtable dsc

我已经使用 1.1 和 xScript 5.1.0.0 中的内置 Script 资源对此进行了测试,并得到了相同的结果。我的设置和测试块工作正常。我正在使用其他几个非常相似的脚本资源,它们对 get 块也能正常工作。

我在语法上尝试了很多变体,但结果总是一样。我知道该块正在运行,因为我注释掉了创建的文件被删除的行并且我看到了该文件。我还在 powershell 中将此作为函数运行,并将输出通过管道传输到 Get-Member,可以看到它确实是一个返回的 hastable。

附带说明一下,我真的不喜欢我在这里使用的通过 DSC 管理此设置的方法。只要它仍在 DSC 中,我对其他想法持开放态度。

Script StorePasswordsUsingReversibleEncyption
{
    SetScript   = {
        secedit /export /cfg c:\temp\secpol.cfg
        (gc C:\temp\secpol.cfg).replace("ClearTextPassword = 1", "ClearTextPassword = 0") | Out-File C:\temp\secpol.cfg
        secedit /configure /db c:\windows\security\local.sdb /cfg c:\temp\secpol.cfg /areas SECURITYPOLICY /quiet
        rm -force c:\temp\secpol.cfg -confirm:$false
    } 

    TestScript = {
        secedit /export /cfg c:\temp\secpol.cfg
        $str = (Get-Content 'c:\temp\secpol.cfg' | select-String 'ClearTextPassword' -SimpleMatch).ToString()
        rm -force c:\temp\secpol.cfg -confirm:$false
        if ($str -eq 'ClearTextPassword = 0') {return $true}
        else {return $false}            
    } 

    # Not working yet           
    GetScript   = {
        secedit /export /cfg c:\temp\secpol.cfg
        $str = (Get-Content 'c:\temp\secpol.cfg' | select-String 'ClearTextPassword' -SimpleMatch).ToString()
        rm -force c:\temp\secpol.cfg -confirm:$false
        return @{Result = $str}     
    }    
}
Run Code Online (Sandbox Code Playgroud)

运行 Get-DSCConfiguration 后,控制台返回的输出如下:

Get-DscConfiguration : PowerShell DSC resource MSFT_ScriptResource  failed to execute Get-TargetResource functionality 
with error message: Failure to get the results from the script in a hash table format. 
At line:1 char:1
+ Get-DscConfiguration
+ ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (MSFT_DSCLocalConfigurationManager:root/Microsoft/...gurationManager)  
   [Get-DscConfiguration], CimException
    + FullyQualifiedErrorId : ProviderOperationExecutionFailure,Get-DscConfiguration
Run Code Online (Sandbox Code Playgroud)

qbi*_*bik 5

尝试这个:

 GetScript   = {
        $null = secedit /export /cfg c:\temp\secpol.cfg
        $str = (Get-Content 'c:\temp\secpol.cfg' | select-String 'ClearTextPassword' -SimpleMatch).ToString()
        rm -force c:\temp\secpol.cfg -confirm:$false
        return @{Result = $str}     
    }    
Run Code Online (Sandbox Code Playgroud)

问题是,当您调用外部命令(如secedit)时,如果此命令(这很自然),它写入标准输出的所有内容都将作为输出返回。但是如果不将它捕获到变量中,它将被进一步传递到脚本块的输出。这return句话也有点误导——它不是“只返回这个东西”,而是“把这个东西写到输出流,然后返回”。

这意味着您的原始文件GetScript不会返回单个哈希表,而是一个如下所示的数组:

@(
  "some-output-from-secedit",
  @{ Result = $str }
)
Run Code Online (Sandbox Code Playgroud)

将外部命令的输出分配给一个变量(我$null在这种情况下用它表示我想丢弃它)将防止它弄乱脚本块的输出。

另一种方法是将命令的输出重定向到Write-Verbose(如果您有兴趣阅读它)或$null(如果您不关心):

secedit /export /cfg c:\temp\secpol.cfg | write-verbose
Run Code Online (Sandbox Code Playgroud)