Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I force Powershell to return an array when a call only returns one object?

Tags:

powershell

I'm using Powershell to set up IIS bindings on a web server, and having a problem with the following code:

$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]

If there's 2+ IPs on the server, fine - Powershell returns an array, and I can query the array length and extract the first and second addresses just fine.

Problem is - if there's only one IP, Powershell doesn't return a one-element array, it returns the IP address (as a string, like "192.168.0.100") - the string has a .length property, it's greater than 1, so the test passes, and I end up with the first two characters in the string, instead of the first two IP addresses in the collection.

How can I either force Powershell to return a one-element collection, or alternatively determine whether the returned "thing" is an object rather than a collection?

like image 233
Dylan Beattie Avatar asked Oct 04 '22 12:10

Dylan Beattie


People also ask

How do you return an array in PowerShell?

First, use the array sub-expression operator @( ... ). This operator returns the result of one or more statements as an array. If there is only one item, the array has only one member. Use Write-Output with the switch -NoEnumerate to prevent PowerShell from un-rolling the array.

How do you call an array in PowerShell?

To create and initialize an array, assign multiple values to a variable. The values stored in the array are delimited with a comma and separated from the variable name by the assignment operator ( = ). The comma can also be used to initialize a single item array by placing the comma before the single item.

How do I return multiple values from a function in PowerShell?

Since PowerShell does not apply any restriction on data type returned, it created a lot of possibilities on what can be returned as an output of the function. So if one needs to return multiple values or objects, it is generally suggested to create an array of the objects and then return the array.

What is @() in PowerShell?

What is @() in PowerShell Script? In PowerShell, the array subexpression operator “@()” is used to create an array. To do that, the array sub-expression operator takes the statements within the parentheses and produces the array of objects depending upon the statements specified in it.


2 Answers

Define the variable as an array in one of two ways...

Wrap your piped commands in parentheses with an @ at the beginning:

$serverIps = @(gwmi Win32_NetworkAdapterConfiguration 
    | Where { $_.IPAddress } 
    | Select -Expand IPAddress 
    | Where { $_ -like '*.*.*.*' } 
    | Sort)

Specify the data type of the variable as an array:

[array]$serverIps = gwmi Win32_NetworkAdapterConfiguration 
    | Where { $_.IPAddress } 
    | Select -Expand IPAddress 
    | Where { $_ -like '*.*.*.*' } 
    | Sort

Or, check the data type of the variable...

IF ($ServerIps -isnot [array])
{ <error message> }
ELSE
{ <proceed> }
like image 197
JNK Avatar answered Oct 21 '22 14:10

JNK


Force the result to an Array so you could have a Count property. Single objects (scalar) do not have a Count property. Strings have a length property so you might get false results, use the Count property:

if (@($serverIps).Count -le 1)...

By the way, instead of using a wildcard that can also match strings, use the -as operator:

[array]$serverIps = gwmi Win32_NetworkAdapterConfiguration -filter "IPEnabled=TRUE" | Select-Object -ExpandProperty IPAddress | Where-Object {($_ -as [ipaddress]).AddressFamily -eq 'InterNetwork'}
like image 17
Shay Levy Avatar answered Oct 21 '22 14:10

Shay Levy