当调用仅返回一个对象时,如何强制Powershell返回数组?
我正在使用Powershell在web服务器上设置IIS绑定,但以下代码有问题:当调用仅返回一个对象时,如何强制Powershell返回数组?,powershell,Powershell,我正在使用Powershell在web服务器上设置IIS绑定,但以下代码有问题: $serverIps = gwmi Win32_NetworkAdapterConfiguration | Where { $_.IPAddress } | Select -Expand IPAddress | Where { $_ -like '*.*.*.*' } | Sort if ($serverIps.length -le 1) { Write-Host
$serverIps = gwmi Win32_NetworkAdapterConfiguration
| Where { $_.IPAddress }
| Select -Expand IPAddress
| Where { $_ -like '*.*.*.*' }
| Sort
if ($serverIps.length -le 1) {
Write-Host "You need at least 2 IP addresses for this to work!"
exit
}
$primaryIp = $serverIps[0]
$secondaryIp = $serverIps[1]
如果服务器上有2个以上的IP,fine-Powershell将返回一个数组,我可以查询数组长度并提取第一个和第二个地址
问题是-如果只有一个IP,Powershell不会返回一个单元素数组,它会返回IP地址(作为字符串,如“192.168.0.100”)-该字符串具有.length
属性,它大于1,因此测试通过,我以字符串中的前两个字符结束,而不是集合中的前两个IP地址
如何强制Powershell返回一个单元素集合,或者确定返回的“thing”是否是对象而不是集合?强制将结果添加到数组中,这样您就可以拥有Count属性。单个对象(标量)没有Count属性。字符串具有长度属性,因此可能会得到错误结果,请使用Count属性:
if (@($serverIps).Count -le 1)...
顺便说一下,不要使用也可以匹配字符串的通配符,而是使用-as运算符:
[array]$serverIps = gwmi Win32_NetworkAdapterConfiguration -filter "IPEnabled=TRUE" | Select-Object -ExpandProperty IPAddress | Where-Object {($_ -as [ipaddress]).AddressFamily -eq 'InterNetwork'}
用两种方法之一将变量定义为数组…
IF ($ServerIps -isnot [array])
{ <error message> }
ELSE
{ <proceed> }
在开始处用@
将管道命令括在括号中:
$serverIps = @(gwmi Win32_NetworkAdapterConfiguration
| Where { $_.IPAddress }
| Select -Expand IPAddress
| Where { $_ -like '*.*.*.*' }
| Sort)
将变量的数据类型指定为数组:
[array]$serverIps = gwmi Win32_NetworkAdapterConfiguration
| Where { $_.IPAddress }
| Select -Expand IPAddress
| Where { $_ -like '*.*.*.*' }
| Sort
或者,检查变量的数据类型…
IF ($ServerIps -isnot [array])
{ <error message> }
ELSE
{ <proceed> }
IF($ServerIps-isnot[array])
{ }
其他的
{ }
如果提前将变量声明为数组,则可以向其中添加元素,即使它只是一个
这应该有用
$serverIps = @()
gwmi Win32_NetworkAdapterConfiguration
| Where { $_.IPAddress }
| Select -Expand IPAddress
| Where { $_ -like '*.*.*.*' }
| Sort | ForEach-Object{$serverIps += $_}
我在将数组传递到Azure部署模板时遇到此问题。如果有一个对象,PowerShell会将其“转换”为字符串。在下面的示例中,
$a
是从一个函数返回的,该函数根据标记的值获取VM对象。我将$a
封装在@()
中,将其传递给新AzureRmResourceGroupDeployment
cmdlet。像这样:
$TemplateParameterObject=@{
VMObject=@($a)
}
New-AzureRmResourceGroupDeployment -ResourceGroupName $RG -Name "TestVmByRole" -Mode Incremental -DeploymentDebugLogLevel All -TemplateFile $templatePath -TemplateParameterObject $TemplateParameterObject -verbose
VMObject
是模板的参数之一
这可能不是最具技术性/健壮性的方法,但对于Azure来说已经足够了
更新 好的,上述方法确实有效。我已经尝试了以上所有方法和一些方法,但我成功地将
$vmObject
作为一个数组传递,与部署模板兼容,其中一个元素如下(我希望MS再次播放(这是一个报告,并在2015年修复了bug)):
$vmObjects
是Get-AzureRmVM的输出
我将$DeserializedJson
传递给部署模板的参数(数组类型)
作为参考,新AzureRmResourceGroupDeployment抛出的可爱错误是
"The template output '{output_name}' is not valid: The language expression property 'Microsoft.WindowsAzure.ResourceStack.Frontdoor.Expression.Expressions.JTokenExpression'
can't be evaluated.."
您可以使用
Measure Object
获取实际对象计数,而无需求助于对象的count
属性
$serverIps = gwmi Win32_NetworkAdapterConfiguration
| Where { $_.IPAddress }
| Select -Expand IPAddress
| Where { $_ -like '*.*.*.*' }
| Sort
if (($serverIps | Measure).Count -le 1) {
Write-Host "You need at least 2 IP addresses for this to work!"
exit
}
您可以在返回列表之前添加逗号(
,
),如return,$list
,也可以在倾向于使用列表的位置将其强制转换为[Array]
或[YourType[]]
。作为引用对象返回,因此它在传递时不会转换
return @{ Value = @("single data") }
为此,他不能用
-is
-检查数据类型吗?字符串有一个.length属性-这就是它工作的原因…:)在@(…)
中包装命令将返回数组,即使对象为零。然而,如果对象为零,则将结果赋给[Array]
类型的变量仍将返回$null。请注意,如果返回的对象是PSObject(可能是其他对象),则这些解决方案都不起作用。@Bagel您能举个例子吗?对我来说,@(…)
对任何类型的对象都能正常工作(产生我希望它应该产生的结果)。很有趣,你怎么又回到了同样的问题上。我有(并且再一次)一个稍微不同的问题,是的,就像在问题中一样,这很好,但当从函数返回时,情况就不同了。如果有一个元素,则忽略该数组,只返回该元素。如果在变量前加逗号,它会将其强制为数组,但多元素数组将返回二维数组。非常乏味。啊,上次也是这样,现在我无法复制了。无论如何,我通过使用Return,$out
解决了我最近的问题,这似乎总是有效的。如果我再次遇到这个问题,我会发布一个例子。我觉得这是最清楚和安全的选择。您可以可靠地在PowerShell的集合或“Foreach”中使用“.Count-ge 1”,这是PowerShell中最烦人的一个方面,也是bug最多的一个方面。我认为您的示例过于复杂。更简单的问题:产生错误。PowerShell 5中是否更改了此行为?我遇到了一个类似的问题,无法在5中重现,但可以在4中重现