Simply outputting something is PowerShell is a thing of beauty - and one its greatest strengths. For example, the common Hello, World! application is reduced to a single line:
"Hello, World!"
It creates a string object, assigns the aforementioned value, and being the last item on the command pipeline it calls the .toString() method and outputs the result to STDOUT (by default). A thing of beauty.
The other Write-* commands are specific to outputting the text to their associated streams, and have their place as such.
Simply outputting something is PowerShell is a thing of beauty - and one its greatest strengths. For example, the common Hello, World! application is reduced to a single line:
"Hello, World!"
It creates a string object, assigns the aforementioned value, and being the last item on the command pipeline it calls the .toString() method and outputs the result to STDOUT (by default). A thing of beauty.
The other Write-* commands are specific to outputting the text to their associated streams, and have their place as such.
I think in this case you will need Write-Output.
If you have a script like
Write-Output "test1";
Write-Host "test2";
"test3";
then, if you call the script with redirected output, something like yourscript.ps1 > out.txt, you will get test2 on the screen test1\ntest3\n in the "out.txt".
Note that "test3" and the Write-Output line will always append a new line to your text and there is no way in PowerShell to stop this (that is, echo -n is impossible in PowerShell with the native commands). If you want (the somewhat basic and easy in Bash) functionality of echo -n then see samthebest's answer.
If a batch file runs a PowerShell command, it will most likely capture the Write-Output command. I have had "long discussions" with system administrators about what should be written to the console and what should not. We have now agreed that the only information if the script executed successfully or died has to be Write-Host'ed, and everything that is the script's author might need to know about the execution (what items were updated, what fields were set, et cetera) goes to Write-Output. This way, when you submit a script to the system administrator, he can easily runthescript.ps1 >someredirectedoutput.txt and see on the screen, if everything is OK. Then send the "someredirectedoutput.txt" back to the developers.
PowerShell Write-Output: Your Friendly Output Companion
Powershell: Write-Output in Function with Return Value
Write output to a file
Redirect write-host outputs to text file
Can Write-Output be used to write to a file?
How do I prevent overwriting a file?
Videos
Hey guys,
Nicholas Xuan Nguyen just wrote a shiny new blog post you may enjoy.
"PowerShell Write-Output: Your Friendly Output Companion"
Summary: Learn all of the ins and outs of the PowerShell Write-Output cmdlet and take control of script and object output in this ATA Learning tutorial!
https://adamtheautomator.com/powershell-write-output/
Yes that is what Write-Output does. It writes output directly to the Output stream, which other parts of the script can pick up on. It is somewhat synonymous with return in this regard.
Depending on what your requirements are there are a number of different streams you could write to.
Write-Error
Write-Warning
Write-Verbose (as you have already picked up on)
Write-Debug
Write-Information
Write-Host (Gets puppies killed though Write-Host Considered Harmful | Jeffrey Snover's blog )
So maybe Write-Information is a better fit. It works in a very similar way to Write-Host except without the stupid colours that people insist on using and you can redirect it off elsewhere if you personally don’t want to read it (I rarely do and for me verbose is usually much more useful if something is going wrong anyway).
I’ve narrowed down a problem I’ve asked about before here so hopefully this will bring about the best answer. My issue is that I need to use Write-Output in many places throughout my script however it will not always work. This occurs when I attempt to use Write-Output in a function that returns a value. So, here are two examples.
This would work:
function hello{
for ($i=0;$i-lt5;$i++){
Write-Output "Hello World $i"
}
}
hello
#Output
Hello World 0
Hello World 1
Hello World 2
Hello World 3
Hello World 4
This would NOT work;
function getOut ($number){
if ($number -eq 1){
Write-Output "Uh oh"
$retVal = "false"
}
else{
Write-Output Woo
$retVal = "true"
}
return $retVal
}
function hello{
$boolQ = 0
$outPut = getOut $boolQ
Write-Output "Finished!"
}
hello
#Output
Finished!
Now, I’m still unsure to the exact cause but from testing, it’s clear that functions that are called in this sort of style:
$val = myFunction
don’t seem to like Write-Output. Now I guess the reason is because the pipe is full with $val or something and I imagine many will suggest Write-Verbose but I honestly am just not a fan of the "Verbose: " part. I’m also writing this to a log using Add-Content (I find Out-File a bit more clunky and I don’t need to read and write at the same time so I’m happy using Add-Content).
I would be happy using verbose however I really need the "Verbose: " bit gone.
Hi there. I have a PowerShell script that I run from our ConfigMgr server that gets me device names when someone provides me with a list of user names.
Right now the script works, but it only outputs all the info to the PowerShell window. I can't get the output to write correctly to a file. I either get just the user names or just the device names, but can't get both.
Here's my latest version of the script:
$a = Get-content "C:\Temp\users.txt"
foreach ($name in $a)
{
$name = "Corp\" + $name
"\n" + $name + "`t"; Get-CMUserDeviceAffinity -UserName "$name" | Select-Object {$_.ResourceName} -ExpandProperty ResourceName | Out-File C:\Temp\userdevice.txt -append`
}
This will write the user names to the PowerShell window and write the device names to my specified output file. That's about as close as I've got to the desired result, which is that I'd like to have each line of my result file contain:
user name [tab character] device name
Write-Output should be used when you want to send data on in the pipeline, but not necessarily want to display it on screen. The pipeline will eventually write it to Out-Default if nothing else uses it first.
Write-Host should be used when you want to do the opposite.
[console]::WriteLine is essentially what Write-Host is doing behind the scenes.
Run this demonstration code and examine the result.
function Test-Output {
Write-Output "Hello, World!"
}
function Test-Output2 {
Write-Host "Hello, World!" -foreground Green
}
function Receive-Output {
process { Write-Host $_ -foreground Yellow }
}
# Output is piped to another function, not displayed in the first.
Test-Output | Receive-Output
# Output us not piped to the 2nd function, only displayed in the first.
Test-Output2 | Receive-Output
# The pipeline sends to Out-Default at the end.
Test-Output
You'll need to enclose the concatenation operation in parentheses, so that PowerShell processes the concatenation before tokenizing the parameter list for Write-Host, or use string interpolation
Write-Host ("count=" + $count)
# or
Write-Host "count=$count"
BTW - Watch this video of Jeffrey Snover explaining how the pipeline works. Back when I started learning PowerShell, I found this to be the most useful explanation of how the pipeline works.
Apart from what Andy mentioned, there is another difference which could be important: Write-Host directly writes to the host and returns nothing, meaning that you can't redirect the output, e.g., to a file.
---- script a.ps1 ----
Write-Host "hello"
Now run in PowerShell:
PS> .\a.ps1 > someFile.txt
hello
PS> type someFile.txt
PS>
As seen, you can't redirect them into a file. This maybe surprising for someone who are not careful.
But if switched to use Write-Output instead, you'll get redirection working as expected.