【问题标题】:How to pass an xml element to a scriptBlock when using invoke-command使用调用命令时如何将 xml 元素传递给 scriptBlock
【发布时间】:2013-07-03 15:42:57
【问题描述】:

使用 PowerShell 3.0,我使用 Invoke-Command cmdlet 将 xmlElement 传递给脚本块。问题是我认为 scriptBlock 将参数作为 arrayList 而不是作为 xmlElement 接收(实际上,我知道接收到的参数是 ArrayList ,因为我注销了 $service.GetType() )。

这是我的 XMLElement:

<Service>
    <ServiceName>Spooler</ServiceName>
    <Startup>Disabled</Startup>
</Service>

这是我的脚本块:

$scptModifyService = {
    param (
        $service
    );
    Set-Service -Name $service.ServiceName -StartupType $service.Startup;
}

这是我调用 scriptBlock 的代码:

## Modify remote Services:
foreach($service in $XML.QCSettings.Services.Service) {
    Invoke-Command -ScriptBlock $scptModifyService -ComputerName $ComputerName -ArgumentList $service;
}

根据我对 Invoke-Command cmdlet (get-help invoke-command) 的了解,ArguementList 可以将对象作为输入,所以我认为这不是我如何调用脚本块的问题上面的“foreach”循环。希望这有点道理。

有没有人知道如何将我的脚本块中的参数捕获为 xmlElement 而不是ArrayList

我已经尝试了几件事(在我的脚本块中):

param( $service = [xml]Get-Content args[0] );

以及该代码的其他变体。

【问题讨论】:

    标签: xml powershell invoke-command


    【解决方案1】:

    从您所展示的内容来看,我看不到脚本块如何获取 ArrayList,但您仍然可以使其工作。 ArrayList 是否包含正确的 XmlElements?如果是这样,您可以通过像这样处理一个或多个服务条目来使您的功能更加健壮:

    $scptModifyService = {
        param (
            [Xml.XmlElement[]]$service
        );
    
        foreach ($s in $service) {
            Set-Service -Name $s.ServiceName -StartupType $s.Startup;
        }
    }
    

    那么你应该可以这样称呼它:

    Invoke-Command -ScriptBlock $scptModifyService -ComputerName $ComputerName -ArgumentList $XML.QCSettings.Services.Service
    

    【讨论】:

    • 感谢您的快速回复!这是我收到的输出:“无法处理参数'服务'的参数转换。无法将值“System.Collections.ArrayList”转换为类型“System.Xml.XmlElement []”。错误:“无法转换”系统。 “System.Collections.ArrayList”类型的 Collections.ArrayList” 值以键入“System.Xml.XmlElement”。” + CategoryInfo : InvalidData: (:) [], ParameterBindin...mationException + FullyQualifiedErrorId : ParameterArgumentTransformationError + PSComputerName : localhost”不知道这里发生了什么......
    • 您可以去掉 $service 参数上的类型说明符[Xml.XmlElement[]],但有些不对劲。当我在具有多个服务节点的 XML 文档上使用它时,它工作得很好。
    • 有什么好方法可以让我查看 arrayList 里面的内容?
    • $service[0].GetType().FullName.
    【解决方案2】:

    在使用 PowerShell 的 [xml] 加速器和动态属性时必须小心。看起来像普通 XML 文档对象模型的东西被转换为 ArrayList 和其他令人讨厌的对象。

    果然,当我将您的 XML 加载到 DOM 中,并在 Service 元素上调用 GetType() 时,我得到了一个 Object[]

    > $xml = [xml]'<QCSettings><Services><Service /><Service /></Services></QCSettings>'
    > $xml.QCSettings.Services.Service.GetType()
    IsPublic IsSerial Name                                     BaseType            
    -------- -------- ----                                     --------            
    True     True     Object[]                                 System.Array        
    

    由于您使用的是 PowerShell 3,因此您可以使用 using 范围来引用远程脚本块内的 XML 块:

    $services = $xml.QCSettings.Services.Service
    Invoke-Command -ScriptBlock { 
        $using:services | ForEach-Object {
            Set-Service $_.ServiceName -StartupType $_.StartupType
        }
    }
    

    由于此代码传入了所有服务对象,因此您只需登录每台计算机一次,而在此之前,您需要为每个服务登录一次。

    如果您不能使用 using 范围,我会使用 ArrayList 并编写您的脚本块来接受对象列表:

    $scptModifyService = {
        param (
            [Object[]]
            $service
        );
        $service | ForEach-Object {
            Set-Service -Name $_.ServiceName -StartupType $_.StartupType
        }
    }
    
    $XML.QCSettings.Services.Service |
        ForEach-Object {
            Invoke-Command -ScriptBlock $scptModifyService -ComputerName $ComputerName -ArgumentList $_
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-12-24
      • 1970-01-01
      • 1970-01-01
      • 2019-11-13
      • 2019-07-03
      • 1970-01-01
      • 2021-05-16
      相关资源
      最近更新 更多