【问题标题】:foreach loop when using Xml.XmlElement in remote scriptblock在远程脚本块中使用 Xml.XmlElement 时的 foreach 循环
【发布时间】:2017-01-18 08:44:29
【问题描述】:

我将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:,则结果输出如下:

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

我很困惑为什么看不到 Vision 应用程序和数据库条目?就像它只是跳过它?更奇怪的是,如果我注释掉

<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\

【问题讨论】:

    标签: xml powershell


    【解决方案1】:

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

    $using:task | Get-Member
    

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

    $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

    【讨论】:

      【解决方案2】:

      因此,根据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
        }
       }
      }
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-26
        • 2015-06-20
        • 1970-01-01
        • 1970-01-01
        • 2015-07-04
        • 1970-01-01
        • 2022-10-17
        • 1970-01-01
        相关资源
        最近更新 更多