带管道或直接输入的多个参数
Multiple parameters with pipeline or direct input
我在 PowerShell 中创建具有多个参数的函数时遇到问题。我有 4 个参数,它们的值可以并且将会通过管道或通过 PowerShell 中的直接输入传递 window.
我似乎无法弄清楚如何确保 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
使用多个参数循环?
参数不是那样工作的。当您通过管道传递输入时,每个参数一次获得一个值(对于每个处理的对象)。在您的命令行调用中,您同时传递所有值,但各个参数数组的索引彼此没有关系,除非您在函数中实现它。否则,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 @_ }
虽然我不确定这会比构建自定义对象和流水线化它们给您带来任何优势。
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
我在 PowerShell 中创建具有多个参数的函数时遇到问题。我有 4 个参数,它们的值可以并且将会通过管道或通过 PowerShell 中的直接输入传递 window.
我似乎无法弄清楚如何确保 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
使用多个参数循环?
参数不是那样工作的。当您通过管道传递输入时,每个参数一次获得一个值(对于每个处理的对象)。在您的命令行调用中,您同时传递所有值,但各个参数数组的索引彼此没有关系,除非您在函数中实现它。否则,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 @_ }
虽然我不确定这会比构建自定义对象和流水线化它们给您带来任何优势。
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