metablaster
metablaster

Reputation: 2184

Powershell function returns an invalid object

Here are 2 equivalent code samples, the only difference is that first sample uses function while other does not.

This code fails, because function returns invalid object:

function Initialize-Table
{
    param (
        [parameter(Mandatory = $false)]
        [string] $TableName = "InstallationTable"
    )

    # Create Table object
    $InstallTable = New-Object System.Data.DataTable "$TableName"

    # Define Columns
    $UserColumn = New-Object System.Data.DataColumn User, ([string])
    $InstallColumn = New-Object System.Data.DataColumn InstallRoot, ([string])

    # Add the Columns
    $InstallTable.Columns.Add($UserColumn)
    $InstallTable.Columns.Add($InstallColumn)

    return $InstallTable
}

Write-Host "Initialize-Table"
Write-Host "***************************"
$InstallTable = Initialize-Table

if (!$InstallTable)
{
    Write-Warning "Table not initialized"
    exit
}

However following is exactly the same, except that function code is put directly into script, and the table is valid!

Write-Host "Initialize-Table"
Write-Host "***************************"
$TableName = "InstallationTable"
# Create Table object
$InstallTable = New-Object System.Data.DataTable "$TableName"

# Define Columns
$UserColumn = New-Object System.Data.DataColumn User, ([string])
$InstallColumn = New-Object System.Data.DataColumn InstallRoot, ([string])

# Add the Columns
$InstallTable.Columns.Add($UserColumn)
$InstallTable.Columns.Add($InstallColumn)

if (!$InstallTable)
{
    Write-Warning "Table not initialized"
    exit
}

Why my function does not work (first sample)? it's the same damn code.

Upvotes: 1

Views: 303

Answers (2)

Kundan
Kundan

Reputation: 1415

As per the official PowerShell documentation the results of each statement are returned as output, even without a statement that contains the Return keyword. Languages like C or C# return only the value or values that are specified by the return keyword.

but when you return a collection from your script block or function, PowerShell automatically unrolls the members and passes them one at a time through the pipeline. This is due to PowerShell's one-at-a-time processing

.

To force a script block or function to return collection as a single object to the pipeline use either Unary array expression or Write-Output with NoEnumerate parameter

e.g. return Write-Output -NoEnumerate $InstallTable; or return ( , $InstallTable);

so below code snippet works well

function Initialize-Table
{
    param (
        [parameter(Mandatory = $false)]
        [string] $TableName = "InstallationTable"
    )

    # Create Table object
    $InstallTable = New-Object System.Data.DataTable "$TableName"

    # Define Columns
    $UserColumn = New-Object System.Data.DataColumn User, ([string])
    $InstallColumn = New-Object System.Data.DataColumn InstallRoot, ([string])

    # Add the Columns
    $InstallTable.Columns.Add($UserColumn)
    $InstallTable.Columns.Add($InstallColumn)


    return  Write-Output -NoEnumerate $InstallTable;
}

Write-Host "Initialize-Table"
Write-Host "***************************"
$InstallTable = Initialize-Table

if (!$InstallTable)
{
    Write-Warning "Table not initialized"
    exit
}

Upvotes: 1

Dmitriy
Dmitriy

Reputation: 21

This works for me:

return ,$InstallTable

Comma operator creates array with 1 member. It will unroll when returning, leaving $InstallTable object intact.

Upvotes: 1

Related Questions