1


How can i force a Powershell function to return an Array?
This simple function for Example, if "C:\New folder" contains only 1 element, it will not return an Array.

function Get-AlwaysArray
{
    $returnArray = gci "C:\New folder"
    Write-Output $returnArray
}
(Get-AlwaysArray).Gettype()

There is already a Thread with a pretty good upvoted answer here But non of the answer works unfortunally.
Here is what i have tried:

function Get-AlwaysArray {
    [Array]$returnArray = gci "C:\New folder"
    Write-Output $returnArray   
}
(Get-AlwaysArray).Gettype()

function Get-AlwaysArray {
    $returnArray = @(gci "C:\New folder")
    Write-Output @($returnArray)   
}
(Get-AlwaysArray).Gettype()

function Get-AlwaysArray {
    $returnArray = @(gci "C:\New folder")
    Write-Output @($returnArray | Where-Object {$_})   
}
(Get-AlwaysArray).Gettype()

function Get-AlwaysArray {
    [Object[]]$returnArray = @(gci "C:\New folder")
    Write-Output @($returnArray | Where-Object {$_})   
}
(Get-AlwaysArray).Gettype()

The only way it would work is

function Get-AlwaysArray {
    $returnArray = gci "C:\New folder"
    Write-Output $returnArray 
}
@(Get-AlwaysArray).Gettype()

But i dont want to add this, everytime i call my function.
What am i doing wrong?

Evilcat
  • 388
  • 3
  • 9
  • I think you should not try to encapsulate this. PowerShell's pipeline output is build around the premise you are trying to avoid. I would always surround with `@()` where I need to use the output and it is needed as an array. – Alex Sarafian Dec 16 '19 at 15:04

2 Answers2

10

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.

$returnArray = @( Get-ChildItem "F:\PowerShell\A" )

Use Write-Output with the switch -NoEnumerate to prevent PowerShell from un-rolling the array.

Write-Output -NoEnumerate $returnArray

You can also effectively achieve the same result using Write-Output without using the -NoEnumerate by using the following syntax below.

Write-Output ,$returnArray

The comma in front of $returnArray effectively creates a new array with $returnArray as its only element. PowerShell then un-rolls this new single-element array, returning the original $returnArray intact to the caller.

Bob M
  • 867
  • 7
  • 5
  • 1
    Nice systematic overview, but note that you need parens in the last command: `Write-Output (,$returnArray)` or - better yet - omit the `Write-Output` and use just `, $returnArray`. – mklement0 Dec 15 '19 at 16:42
-2

try this one,

function Get-AlwaysArray
{

    $returnArray = Get-ChildItem "F:\PowerShell\A"
    Write-Output $()$returnArray
}

(Get-AlwaysArray).Gettype()

IsPublic IsSerial Name                                     BaseType                                                                  
-------- -------- ----                                     --------                                                                  
True     True     Object[]                                 System.Array                                                              
mklement0
  • 382,024
  • 64
  • 607
  • 775
trampCoder
  • 27
  • 2
  • 1
    Bad idea, this will always add a`$Null` as the first item to your array. – iRon Dec 15 '19 at 09:40
  • Good point, @iRon. In addition to the unwanted `$null`, the approach is ineffective in Windows PowerShell. Only in PowerShell Core (v6+) do you get `$returnArray` as a _single_ output object (as the 2nd output object after the unwanted `$null`). – mklement0 Dec 15 '19 at 16:11
  • @trampCoder: To (indirectly) show that `$null` is being added, try `function foo() { Write-Output $() (1,2) }; foo | % { "[$_]" }` (inside an expandable string, `$null` expands to an empty string). – mklement0 Dec 15 '19 at 16:41