0

I wasn't sure how to describe this problem in the title so here goes. I call a function from a script in another script. In that function i have a while loop that basically keeps looping through a set of ip's and looks up their hostname. when the while loop times out or we have all the host names. it returns the hostnames.

My problem is that the return value contains every single Write-Host i'm doing in that function.

i know it's because Write-Host puts stuff on the pipeline and the return just returns whatever it has.

How do i go about fixing this? The entire script i run get's logged in a log file which is why i want to have some verbose logging.

| out-null on write-host fixes the issue but it doesn't print the write-host values in the script.

in main.psm1 i have a function like so:

$nodes = @("ip1", "ip2", "ip3", "ip4")
$nodesnames = DoStuff -nodes $nodes

then in functions.psm1 i have functions like:

Function DoStuff
{
    param($nodes)
    $timeout = 300
    $timetaken = 0


    $sleepseconds = 5
    $nodenames = @("$env:COMPUTERNAME")

    while(($nodenames.count -lt $nodes.count) -and ($timetaken -lt $timeout))
    {
        try 
        {
            Write-Host "Stuff"
            foreach($node in $nodes)
            {
                $nodename = SuperawesomeFunction $node
                Write-Host "$nodename"
                if($nodenames -notcontains $nodename)
                {
                    $nodenames += @($nodename)
                }
            }
        }
        catch
        {
            Write-Host "DoStuff Failed because $_"
        }
        Start-Sleep $sleepseconds
        $timetaken += $sleepseconds
    }
    return $nodenames
}

Function SuperawesomeFunction 
{
    param($node)
    $nodename = [System.Net.Dns]::GetHostEntry("$node")
    return $nodename
}

Thanks.

Puzzle84
  • 540
  • 3
  • 20
  • The code that you are running must be fairly different than the example that you have provided. The above seems to run as expected, and the Write-Host info is indeed written to the screen, and local computer name followed by the DNS lookup info for the IP's is returned as expected. – TheMadTechnician Apr 08 '15 at 03:57
  • actually true. my bad. the only difference is that the write-host is an echo – Puzzle84 Apr 08 '15 at 04:03
  • That is a huge difference. echo is an alias of Write-Output. Functions return most everything to the pipeline, including Return statement, write-output, or things that are not specifially directed elsewhere. Write-Host specifically instructs PowerShell to direct that information to the host (PowerShell Console or ISE most likely). – TheMadTechnician Apr 08 '15 at 04:38

1 Answers1

3

So the answer is, your function is working like it is by design. In PowerShell a function will return output in general to the pipeline, unless specifically directed otherwise.

You used Echo before, which is an alias of Write-Output, and output is passed down the pipe as I mentioned before. As such it would be collected along with the returned $nodenames array.

Replacing Echo with Write-Host changes everything because Write-Host specifically tells PowerShell to send the information to the host application (usually the PowerShell Console or PowerShell ISE).

How do you avoid this? You could add a parameter specifying a path for a logfile, and have your function update the logfile directly, and only output the relevant data.

Or you can make an object with a pair of properties that gets passed back down the pipe which has the DNS results in one property, and the errors in another.

You could use Write-Error in the function, and set it up as an advanced function to support -errorvariable and capture the errors in a separate variable. To be honest, I'm not sure how to do that, I've never done it, but I'm 90% sure that it can be done.

TheMadTechnician
  • 34,906
  • 3
  • 42
  • 56
  • Thanks for the explanation. i could have figured this out on my own i think. Alrighty swap out echo and change to Write-Host – Puzzle84 Apr 08 '15 at 04:47