script - powershell tutorial
¿Cómo puedo forzar a Powershell a devolver una matriz cuando una llamada solo devuelve un objeto? (4)
Fuerza el resultado a una matriz para que puedas tener una propiedad Count. Los objetos individuales (escalares) no tienen una propiedad de Cuenta. Las cadenas tienen una propiedad de longitud para que pueda obtener resultados falsos, use la propiedad Count:
if (@($serverIps).Count -le 1)...
Por cierto, en lugar de usar un comodín que también puede coincidir con cadenas, use el operador -as:
[array]$serverIps = gwmi Win32_NetworkAdapterConfiguration -filter "IPEnabled=TRUE" | Select-Object -ExpandProperty IPAddress | Where-Object {($_ -as [ipaddress]).AddressFamily -eq ''InterNetwork''}
Estoy usando Powershell para configurar enlaces IIS en un servidor web y tengo un problema con el siguiente código:
$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]
Si hay más de 2 direcciones IP en el servidor, bien: Powershell devuelve una matriz y puedo consultar la longitud de la matriz y extraer la primera y la segunda direcciones.
El problema es que si solo hay una IP, Powershell no devuelve una matriz de un elemento, devuelve la dirección IP (como una cadena, como "192.168.0.100"): la cadena tiene una propiedad .length
, es mayor que 1 , por lo que la prueba pasa, y termino con los dos primeros caracteres en la cadena, en lugar de las dos primeras direcciones IP en la colección.
¿Cómo puedo forzar a Powershell a devolver una colección de un elemento o, alternativamente, determinar si la "cosa" devuelta es un objeto en lugar de una colección?
Si declara la variable como una matriz antes de tiempo, puede agregarle elementos, incluso si es solo uno ...
Esto debería funcionar...
$serverIps = @()
gwmi Win32_NetworkAdapterConfiguration
| Where { $_.IPAddress }
| Select -Expand IPAddress
| Where { $_ -like ''*.*.*.*'' }
| Sort | ForEach-Object{$serverIps += $_}
Tuve este problema pasando una matriz a una plantilla de implementación de Azure. Si había un objeto, PowerShell lo "convirtió" en una cadena. En el siguiente ejemplo, se devuelve $a
desde una función que objeta la VM según el valor de una etiqueta. Paso el $a
a al cmdlet New-AzureRmResourceGroupDeployment
envolviéndolo en @()
. Al igual que:
$TemplateParameterObject=@{
VMObject=@($a)
}
New-AzureRmResourceGroupDeployment -ResourceGroupName $RG -Name "TestVmByRole" -Mode Incremental -DeploymentDebugLogLevel All -TemplateFile $templatePath -TemplateParameterObject $TemplateParameterObject -verbose
VMObject
es uno de los parámetros de la plantilla.
Puede que no sea la forma más técnica / robusta de hacerlo, pero es suficiente para Azure.
Actualizar
Bueno, lo anterior funcionó. He intentado todo lo anterior y algunos, pero la única forma en que he logrado pasar $vmObject
como una matriz, compatible con la plantilla de implementación, con un elemento es la siguiente (espero que MS haya estado jugando de nuevo (este era un informe) y error solucionado en 2015)):
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")
foreach($vmObject in $vmObjects)
{
#$vmTemplateObject = $vmObject
$asJson = (ConvertTo-Json -InputObject $vmObject -Depth 10 -Verbose) #-replace ''/s'',''''
$DeserializedJson = (New-Object -TypeName System.Web.Script.Serialization.JavaScriptSerializer -Property @{MaxJsonLength=67108864}).DeserializeObject($asJson)
}
$vmObjects
es el resultado de Get-AzureRmVM.
Paso $DeserializedJson
al parámetro ''plantilla de despliegue'' (de tipo array).
Como referencia, el encantador error que arroja New-AzureRmResourceGroupDeployment
es
"The template output ''{output_name}'' is not valid: The language expression property ''Microsoft.WindowsAzure.ResourceStack.Frontdoor.Expression.Expressions.JTokenExpression''
can''t be evaluated.."
Defina la variable como una matriz en una de dos formas ...
Ajustar sus comandos canalizados entre paréntesis con un @
al comienzo:
$serverIps = @(gwmi Win32_NetworkAdapterConfiguration
| Where { $_.IPAddress }
| Select -Expand IPAddress
| Where { $_ -like ''*.*.*.*'' }
| Sort)
Especifique el tipo de datos de la variable como una matriz:
[array]$serverIps = gwmi Win32_NetworkAdapterConfiguration
| Where { $_.IPAddress }
| Select -Expand IPAddress
| Where { $_ -like ''*.*.*.*'' }
| Sort
O bien, verifique el tipo de datos de la variable ...
IF ($ServerIps -isnot [array])
{ <error message> }
ELSE
{ <proceed> }