【问题标题】:Multiple parameters with pipeline or direct input具有管道或直接输入的多个参数
【发布时间】:2018-06-01 07:23:11
【问题描述】:

我在 PowerShell 中创建具有多个参数的函数时遇到问题。我有 4 个参数,它们的值可以并且将通过管道或通过 PowerShell 窗口中的直接输入传递。

我似乎无法弄清楚如何确保这 4 个参数可以在流程部分使用。

这是我所拥有的(Write-Host 部分当然仅用于测试):

function Set-NewDevEnv {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true, ValuefromPipelineByPropertyName=$true)]
        [ValidateSet('IIS', 'SQL', 'SOLR', 'Vanilla')]
        [string[]]$VMType,
        [Parameter(Mandatory=$true, ValuefromPipelineByPropertyName=$true)]
        [string[]]$StaticIP,
        [Parameter(Mandatory=$true, ValuefromPipelineByPropertyName=$true)]
        [string[]]$VMName,
        [Parameter(Mandatory=$true, ValuefromPipelineByPropertyName=$true)]
        [string[]]$VMDNSName
    )

    Begin {}

    Process {
        Write-Host "VMType is $VMType ; StaticIP is $StaticIP ; VMName is $VMName; and VMDNSName is $VMDNSName"
    }

如果我使用它,它适用于管道输入,但不适用于直接命令行输入,即:

Set-NewDevEnd -VMType "SQL","IIS" -StaticIp "192.168.0.1","192.168.0.2" -VMName "Testing1","Testing2" -VMDNSName "Testing1","Testing2"

我来了

VMType 是 SQL IIS ;静态IP为 192.168.0.1 192.168.0.2 ; VMName 是 Testing1 Testing2 ;并且 VMDNSName 是 Testing1 Testing2

我知道通常情况下,要同时支持直接输入和管道输入,您需要在process 部分添加一个foreach 循环,但是我将如何使用带有多个参数的foreach 循环呢?

【问题讨论】:

    标签: function powershell parameter-passing pipeline


    【解决方案1】:

    参数不是这样工作的。当您通过管道传递输入时,每个参数一次获取一个值(对于每个处理的对象)。在您的命令行调用中,您同时传递所有值,但各个参数数组的索引彼此没有关系,除非您在函数中实现它。否则,PowerShell 应该如何处理具有(例如)两个参数的函数,这些参数需要一个字符串数组和一个简单的字符串?同时处理数组和简单值?每个数组索引以及简单字符串的副本?第一个索引是简单的字符串,其余的索引是空值?还有什么?

    您可以做的是构建一个哈希表列表并将它们循环播放:

    $data = @{
        'VMType'    = 'SQL'
        'StaticIP'  = '192.168.0.1'
        'VMName'    = 'Testing1'
        'VMDNSName' = 'Testing1'
    },
    @{
        'VMType'    = 'IIS'
        'StaticIP'  = '192.168.0.2'
        'VMName'    = 'Testing2'
        'VMDNSName' = 'Testing2'
    }
    
    $data | ForEach-Object { Set-NewDevEnv @_ }
    

    虽然我不确定与构建自定义对象和流水线相比,这会给您带来什么优势。

    【讨论】:

      【解决方案2】:

      ValuefromPipelineByPropertyName 表示您需要在传递给输入的对象中具有同名的属性。参数的类型也不需要是数组。你可以这样改变函数:

      Function Set-NewDevEnv {
          [cmdletbinding()]
          param (
              [Parameter(Mandatory=$true,ValuefromPipelineByPropertyName=$true)]
              [ValidateSet('IIS','SQL','SOLR','Vanilla')]
              [string]$VMType,
              [Parameter(Mandatory=$true,ValuefromPipelineByPropertyName=$true)]
              [string]$StaticIP,
              [Parameter(Mandatory=$true,ValuefromPipelineByPropertyName=$true)]
              [string]$VMName,
              [Parameter(Mandatory=$true,ValuefromPipelineByPropertyName=$true)]
              [string]$VMDNSName
          )
      
          begin {"Test Begin"}
          process {
              Write-Host "VMType is $VMType ; StaticIP is $StaticIP ;" + `
              "VMName is $VMName; and VMDNSName is $VMDNSName"
          }
          end {"Test End"}
      }
      

      然后进行测试:

      @([pscustomobject]@{
          VMType = "SQL";
          StaticIP = "192.168.0.1";
          VMName = "Testing1";
          VMDNSName= "Testing1"; }, 
        [pscustomobject]@{
          VMType = "IIS";
          StaticIP = "192.168.0.2";
          VMName = "Testing2";
          VMDNSName= "Testing2";}) | Set-NewDevEnv
      

      结果如下:

      Test Begin
      VMType is SQL ; StaticIP is 192.168.0.1 ; VMName is Testing1; and VMDNSName is Testing1
      VMType is IIS ; StaticIP is 192.168.0.2 ; VMName is Testing2; and VMDNSName is Testing2
      Test End
      

      【讨论】:

      • 谢谢! Ansgar 和您的答案几乎相同,呵呵但是您的答案,通过使用自定义对象,对我的帮助更大,因为我将专门调用这些值来在 VMware 中构建新的 VM。谢谢你的帮助! :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-18
      • 1970-01-01
      • 2017-10-12
      • 1970-01-01
      相关资源
      最近更新 更多