31
votes

I'm confused about the difference between echo and Write-Host in PowerShell. I have two files, POC.ps1 & validatePath.ps1. These files are on my local machine, and I'm running them on a remote machine using Invoke-Command. I am using PowerShell v3.0.

To execute both of these scripts I use the command:

.\POC.ps1 -filename C:\Users  -user Blaine

Here are the two files:

POC.ps1:

param($filename, $user)

echo $filename
echo "This"
echo $user

$responseObject = Invoke-Command testcomputer -FilePath .\validatePath.ps1  -ArgumentList($filename, $user) -AsJob

while($responseObject.State -ne "Completed")
{

}

$result = Receive-Job -Id $responseObject.Id -Keep
echo $result

Here is where things get weird...

validatePath.ps1:

Param([string] $filename,
      [string] $user)

function ValidatePath( $filename, $user, $fileType = "container" )
{
    Write-Host "This is the file name: $filename"
    Write-Host "This is user: $user"  <--- Notice I'm using Write-Host here
    $fileExist = $null
    if( -not (test-path $filename -PathType $fileType) )
    {
        throw "$user, the path $filename does not exist!"

    }
    else
    {
         Write-Host "This is the second part"
         echo $filename found!
    }
    Write-Host "This is the third part"
    return $fileExist
}


try
{

    ValidatePath($filename, $user)
}
catch
{
    $e = $_.Exception
    echo $e
}

When I run the above script, this is the output:

C:\Users
This
Blaine
This is the file name: C:\Users Blaine
This is user:  <--- Notice where this line is?
This is the second part
This is the third part
C:\Users
Blaine
found!

But if I change the validatePath.ps1 to this:

Param([string] $filename,
      [string] $user)

function ValidatePath( $filename, $user, $fileType = "container" )
{
    Write-Host "This is the file name: $filename"
    echo "This is user: $user" <---notice I'm using Echo here
    $fileExist = $null
    if( -not (test-path $filename -PathType $fileType) )
    {
        throw "$user, the path $filename does not exist!"

    }
    else
    {
         Write-Host "This is the second part"
         echo $filename found!
    }
     Write-Host "This is the third part"
    return $fileExist
}


try
{

    ValidatePath($filename, $user)
}
catch
{
    $e = $_.Exception
    echo $e
}

This is the output:

C:\Users
This
Blaine
This is the file name: C:\Users Blaine
This is the second part
This is the third part
This is user: <---- Notice where this line is now?
C:\Users
Blaine
found!

You will notice that the line "This is the user:" is in different spots. Why is this? Why does echo work differently than Write-Host?

UPDATE:

What is even more strange is that if I rerun the script twice like this:

POC.ps1:

param($filename, $user)

echo $filename
echo "This"
echo $user

$responseObject = Invoke-Command CAPTESTPK01 -FilePath .\validatePath.ps1  -ArgumentList $filename, $user -AsJob

while($responseObject.State -ne "Completed")
{

}

$result = Receive-Job -Id $responseObject.Id -Keep
echo $result


$filename = "C:\saddfasdfj"

#Here I run the command again, using a different file name
$responseObject = Invoke-Command CAPTESTPK01 -FilePath .\validatePath.ps1  -ArgumentList $filename, $user -AsJob

while($responseObject.State -ne "Completed")
{
   if($responseObject.State -eq "Failed")
   {
        echo "Failed"
        $result = Receive-Job -Id $responseObject.Id -Keep
        echo $result
        break
   }
}

$result = Receive-Job -Id $responseObject.Id -Keep
echo $resul

It gives me this output when using echo in validatePath.ps1:

C:\Users
This
Blaine
This is the file name: C:\Users
This is the second part
This is the third part
This is user: Blaine <---- This line is here
C:\Users
found!
This is the file name: C:\saddfasdfj
This is user: Blaine <---- But now it's here, where it should be? Wth?
Blaine, the path C:\saddfasdfj does not exist!
2
Not an answer to your question, but arguments to PowerShell functions should not be put in parenthesis when called. It should be ValidatePath $filename $userLars Truijens
That probably answers my question here: stackoverflow.com/questions/17623712/… Thanks.BlackHatSamurai

2 Answers

68
votes

echo is an alias for Write-Output, which writes to the Success output stream. This allows output to be processed through pipelines or redirected into files. Write-Host writes directly to the console, so the output can't be redirected/processed any further.

15
votes

echo is an alias for Write-Output. Where Write-Host directly writes to the 'screen', Write-Output writes to the pipeline. If the pipeline is not feed into some other command it ends on the 'screen' in the end as well. The difference you see is Write-Host getting written to the screen directly where Write-Output first goes through the pipeline and ends up on the screen after Write-Host.

Using Write-Output allows you to pipe/redirect the output to a file or to another command, where Write-Host does not. They should be used depending on what you want.

See here for more.