Reputation: 13
Consider the following PowerShell script:
function Alpha {
# write-output 'Uncomment this line and see what happens.';
return 65;
}
function Bravo {
$x = Alpha;
$y = $x -eq 65;
return $y;
}
$z = Bravo;
echo $z;
On my computer (which is running Windows XP SP3, .NET 4.0, and PowerShell 2.0 RTM), when the script is run, the script's output is as expected (True
). However, when "the line" is uncommented (and the script is run again), instead of seeing the same output prepended by Uncomment this line...
, I am only seeing 65
. Can someone please explain what is going on? Thanks.
Upvotes: 1
Views: 567
Reputation: 11
One must be very careful when returning values from a function. If "echo" (write-output) is used before function's "return" statement, it will damage the return e.g. ... echo "123" ; return $false --- this will resolve to $true.
# both function should return $false but the first one is evaluated to $true
function test_NG {Write-Output "this text WILL be included with the return value" ; return $false}
function test_OK {Write-Host "this text will NOT be included with the return value but visible on the screen" ; return $false}
if (test_NG) {"OK"} else {"NG"} # this should resolve to NG but is OK because write-output added the text to the return value
if (test_OK) {"OK"} else {"NG"} # correct result (NG) but the text is always displayed, even during this evaluation
Upvotes: 1
Reputation: 13
@Johannes Rössel: Thank you for your explanation. You know, I am a C# programmer (this explains the semicolons) and I am asking this question because an echo
debugging statement (a statement which is usually inert in other languages) totally broke my script in strange ways. After tracing down the supposed "strange behavior" for almost an hour, I came up with the script above, narrowing down the "strange behavior" to just two functions.
Thanks to your explanation, now I know two important PowerShell gotchas:
echo
(Write-Output
) statement changes (adds to) a function's return value, andreturn
statement adds to (instead of sets) a function's return value, possibly to form an array.Indeed, both gotchas can be verified by running the following PowerShell commands:
function Charlie { echo 2; echo 3; echo 5; return 7 }
$a = Charlie
# Nothing is printed.
$a
# Displays the contents of array $a, that is:
# 2
# 3
# 5
# 7
Now I probably want to write all my PowerShell debugging statements with the Write-Warning
statement instead. After all, their outputs are colored yellow, so they can be read and distinguished more easily.
Upvotes: 0
Reputation: 354516
Write-Output
just writes an object to the pipeline. If you need a message displayed on the screen, use Write-Host
.
So, to take apart what happens here, that was kind of a preliminary. If you uncomment the line, both the string 'Uncomment this line and see what happens.'
and the number 65
are outputs of the function, so when calling Bravo
the variable $y
no longer holds just a single value but instead the array 'Uncomment this line and see what happens.',65
.
Now the comparison operators work differently if the left operand is an array instead of a scalar value. If the left operand is an array they simply return all elements from the array where the condition would be $true
. In this case, since you compare with 65
, it will return all items that are equal to 65
. So the result is no longer a boolean but instead an array of objects (or in this case, just a single object) – 65
.
Upvotes: 3