22

I am a Powershell noobie and I am currently writing my second script so bear with me. I am trying to do a write-host and output my write-host message along with a time stamp and what computer is completing my various script blocks to a text file and I am having issues with which syntax to make things work.

I tried the following for testing purposes. This will be going to a server once I get the Syntax down - for now it goes to my local C: drive.

write-host "folders created successfully $env:computername" >> c:\scripts\testlog.txt

The behavior I'm seeing is the text file is being created but there's no contents in it - all blank.

Knut Holm
  • 3,988
  • 4
  • 32
  • 54
h34th3r
  • 221
  • 1
  • 2
  • 3
  • 2
    What happens with you change `Write-Host` to `Write-Output`? Host is sent to console not standard output – Matt Mar 02 '15 at 14:43

4 Answers4

32

Use the Start-Transcript cmdlet - it can capture Write-Host output as follows:

Start-Transcript -Path .\testlog.txt
Write-Host "Hello World"
Stop-Transcript
Lars Fastrup
  • 5,458
  • 4
  • 31
  • 35
  • 2
    There is all sorts of rubbish dumped in the file with this – Alan Macdonald Dec 21 '21 at 11:04
  • Didn't work and doesn't seem like a clean solution anyway. – Mike Q Sep 01 '22 at 02:10
  • But what you can do with it is catch the verbose output of a variable, which is shown if you do `Write-Host $a`. With `Write-Output $a` I just see a column-based summary. Hope you know, what I mean (e.g. when you have some sophisticated function outputs in $a) – spikey Jan 20 '23 at 05:30
27

Write-Host does not use standard out. It always outputs to the console directly, skipping anything else. Write-Output does output to standard out.

To do answer your specific question -- how to append the output of a command to a text file -- you could use:

Write-Output "folders created successfully $env:computername" >> C:\scripts\testlog.txt

However, you could also use Add-Content:

Add-Content -Path C:\scripts\testlog.txt -Value "folders created successfully $env:computername"

Or you can pipe to Out-File -Append:

"folders created successfully $env:computername" | Out-File -FilePath C:\scripts\testlog.txt -Append

Why would you use different methods? They have a few differences which you won't run into very often. The redirection operators don't give you as much control over what happens (encoding, etc.).

Bacon Bits
  • 30,782
  • 5
  • 59
  • 66
6

Write-Host is only for sending data to the console and nowhere else. If you are looking to send data elsewhere ie. to file you will need to send it to the output stream

write-output "folders created successfully $($env:computername)" >> c:\scripts\testlog.txt

or

"folders created successfully $($env:computername)" >> c:\scripts\testlog.txt

Notice the sub expression around $env. We need to be sure that the variable is expanded in the double quotes properly.

Look at Bacons answer for how to do this with native PowerShell cmdlets

Community
  • 1
  • 1
Matt
  • 45,022
  • 8
  • 78
  • 119
  • 1
    I have computer name coming out of a CSV file that I imported $computername = $viewobject.desktop what I would like is for it to append to the text file with where the write-output is being written from Write-Output ("VMWare Backup folder created") >> \\servername\dump\test1.txt}} The text file is not being created. Does it have to be created ahead of time? I tried that and no words are being output into the text file. – h34th3r Mar 04 '15 at 17:07
  • 1
    @h34th3r Is there a question in there? Are you no using environment variables?... ah you edited the comment. No the file does not need to exist ahead of time. If I try that small snippet I get a file with "VMWare Backup folder created" as the content – Matt Mar 04 '15 at 17:10
0

As other answers already pointed out, Write-Output is the cmdlet that writes to the output stream, and can be used to redirect that output to a file. However, note its following trait which makes an important difference to Write-Host when it's used inside functions:

Using Write-Output:

Function Get-SomeResult {
    Write-Output "Some logging here"
    return "My desired result"
}

Function Start-Something {
    $result = Get-SomeResult
    Write-Output "The result is: $result"
}

Start-Something >> "$PSScriptRoot\MyLog.log"

The log will be:

The result is: Some logging here My desired result

As you can see, the output has become part of the returned object $result, which is likely unintended.

Using Write-Host:

Function Get-SomeResult {
    Write-Host "Some logging here"
    return "My desired result"
}

Function Start-Something {
    $result = Get-SomeResult
    Write-Host "The result is: $result"
}

Start-Something >> "$PSScriptRoot\MyLog.log"

The log will be, as expected:

Some logging here

The result is: My desired result

The returned object of the Get-SomeResult function is therefore retaining the value that we meant to set.

Output to file function

One way to address this is to create a separate function such as the following, to avoid repeating the log path inside the script:

$script:logPath = "$PSScriptRoot\MyLog.log"

Function Write-Log {
    param($Message)
    Write-Output $Message >> $script:logPath
}

Function Get-SomeResult {
    Write-Log "Some logging here"
    return "My desired result"
}

Function Start-Something {
    $result = Get-SomeResult
    Write-Log "The result is: $result"
}

Start-Something

Our new Write-Log can then be used just as Write-Output but without that potentially unintended characteristic. It can be further extended for validation or replicating other parameters of Write-Output, but this simple format may do for most use-cases.

Siavas
  • 4,992
  • 2
  • 23
  • 33