1

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.

5
  • I notice a difference, you never define $TableName in the 2nd code. Commented Dec 25, 2019 at 3:42
  • @BillyHudson ok, I forgot while posting a question, I'll update my sample, but that isn't an issue. Commented Dec 25, 2019 at 3:46
  • In what way is the returned object invalid? Commented Dec 25, 2019 at 4:06
  • It's invalid because if(!$InstallTable) check fails, and I'm unable to use the variable to write and read data into the table. Commented Dec 25, 2019 at 4:19
  • I managed to solve the problem by making the table global variable, it's unfortunate that in powershell return means write to stdout. (so powershell tries to write NET object to console) in every programming language return does exactly what it's name implies, but here return mean no return Commented Dec 25, 2019 at 6:45

2 Answers 2

1

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
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you and Dmitry, +1 for both, I'm already rewriting my code.
1

This works for me:

return ,$InstallTable

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.