当调用仅返回一个对象时,如何强制Powershell返回数组?

当调用仅返回一个对象时,如何强制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

我正在使用Powershell在web服务器上设置IIS绑定,但以下代码有问题:

$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中重现