在远程scriptblock

时间:2017-01-17 19:20:42

标签: xml powershell

我将一个XmlElement传递给一个函数,该函数又将XmlElement传递给一个脚本块进行远程执行。发生的是只有部分元素通过foreach循环读取。如果我使用$using传递XML或将其作为ArrayList传递,这似乎无关紧要。

XML部分:

<task>
    <apps>
        <app name="Sample">
            <db name="Basic"/>
            <db name="Interntl"/>
            <db name="Xchgrate"/>
        </app>
        <app name="Vision">
            <db name="Plan1"/>
        </app>
    </apps>
</task>

PowerShell代码:

foreach ($App in $using:task.apps.app) {
  $AppName = $App.name
  foreach ($Db in $App.db) {
    $DbName = $Db.name
    $AppFolder = "$DestinationFolder\$AppName\$DbName"
    $AppFolder
  }
}

如果$DestinationFolder设置为C:\ Staging:

,则结果输出为this
C:\Staging\Objects\Applications\Sample\Basic
C:\Staging\Objects\Applications\Sample\Interntl
C:\Staging\Objects\Applications\Sample\Xchgrate

我很困惑为什么我没有看到Vision app和db条目?它就像它只是跳过它?更奇怪的是,如果我发表评论

<db name="Plan1"/>

输出中包含Vision应用程序。

C:\Staging\Objects\Applications\Sample\Basic
C:\Staging\Objects\Applications\Sample\Interntl
C:\Staging\Objects\Applications\Sample\Xchgrate
C:\Staging\Objects\Applications\Vision\

2 个答案:

答案 0 :(得分:0)

scriptblock中的对象变为Deserialized.System.Xml.XmlElement对象,其显然与常规System.Xml.XmlElement对象略有不同。您可以通过在scriptblock中运行类似的内容来查看对象类型:

$using:task | Get-Member

要避免此问题,请在scriptblock之外创建文件夹列表,并在调用远程主机上的scriptblock时将字符串数组作为参数传递:

$AppFolders = foreach ($App in $task.apps.app) {
  foreach ($Db in $App.db) {
    '{0}\{1}\{2}' -f $DestinationFolder, $App.name, $Db.name
  }
}

Invoke-Command -Computer 'remotehost' -ScriptBlock {
  Param($folders)
  ...
} -ArgumentList (,$AppFolders)

需要使用表达式,$AppFolders来避免展开数组。没有它,只有列表的第一个元素会传递给$folders

答案 1 :(得分:0)

因此,根据此answer,您需要将节点包装到新的XML文档对象中并将其传递到脚本块中。因此,对我有用的就是这样做

$wrapper = New-Object System.Xml.XmlDocument
$wrapper.AppendChild($wrapper.ImportNode($task, $true)) | Out-Null

然后通过-ArgumentList(,$ wrapper)

传递$ wrapper
$sb = {
 param([object]$wrapper)
 foreach ($App in $wrapper.task.apps.app) {
  $AppName = $App.name
  foreach ($Db in $App.db) {
    $DbName = $Db.name
    $AppFolder = "$DestinationFolder\$AppName\$DbName"
    $AppFolder
  }
 }
}

像魅力一样工作!感谢您的帮助。