In doing some Powershell automation, I'm having trouble with the way that data written to stdout by a .cmd
file is automatically captured. I have two functions that do something like the following:
function a {
& external.cmd # prints "foo"
return "bar"
}
function b {
$val = a
echo $val # prints "foobar", rather than just "bar"
}
Basically, data that external.cmd
sends to stdout is added to the return value of a
, even though all I really want to return from a
is the string that I specified. How can I prevent this?
Here are a few different approaches for handling this:
capture the output of the .cmd
script:
$output = & external.cmd # saves foo to $output so it isn't returned from the function
redirect the output to null (throw it away)
& external.cmd | Out-Null # throws stdout away
redirect it to a file
& external.cmd | Out-File filename.txt
ignore it in the caller by skipping it in the array of objects that's returned from the function
$val = a
echo $val[1] #prints second object returned from function a (foo is object 1... $val[0])
In PowerShell, any output value your code does not capture, is returning the "caller" object (including stdout, stderr, etc). So you have to capture or pipe it to something that doesn't return a value, or you'll end up with the object[]
itself as your return value from the function.
The return
keyword is really just for clarity, with the exact same effect as just writing the variable alone (as shown), but with an immediate exit of a script block in PowerShell. Something like this would even work (not verbatim but just to give you the idea):
function foo()
{
"a"
"b"
"c"
}
PS> $bar = foo
PS> $bar.gettype()
System.Object[]
PS> $bar
a
b
c
function foobar()
{
"a"
return "b"
"c"
}
PS> $myVar = foobar
PS> $myVar
a
b