Reputation: 2184
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
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
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