I'm running a PowerShell script against many servers, and it is logging output to a text file.
I'd like to capture the server the script is currently running on. So far I have:
$file = "\\server\share\file.txt"
$computername = $env:computername
$computername | Add-Content -Path $file
This last line adds question marks in the output file. Oops.
How do I output a variable to a text file in PowerShell?
The simplest Hello World example...
$hello = "Hello World"
$hello | Out-File c:\debug.txt
After some trial and error, I found that
$computername = $env:computername
works to get a computer name, but sending $computername
to a file via Add-Content doesn't work.
I also tried $computername.Value
.
Instead, if I use
$computername = get-content env:computername
I can send it to a text file using
$computername | Out-File $file
Note: The answer below is written from the perspective of Windows PowerShell.
However, it applies to the cross-platform PowerShell Core edition as well, except that the latter - commendably - consistently defaults to BOM-less UTF-8 character encoding, which is the most widely compatible one across platforms and cultures..
To complement bigtv's helpful answer helpful answer with a more concise alternative and background information:
# > $file is effectively the same as | Out-File $file
# Objects are written the same way they display in the console.
# Default character encoding is UTF-16LE (mostly 2 bytes per char.), with BOM.
# Use Out-File -Encoding <name> to change the encoding.
$env:computername > $file
# Set-Content calls .ToString() on each object to output.
# Default character encoding is "ANSI" (culture-specific, single-byte).
# Use Set-Content -Encoding <name> to change the encoding.
# Use Set-Content rather than Add-Content; the latter is for *appending* to a file.
$env:computername | Set-Content $file
When outputting to a text file, you have 2 fundamental choices that use different object representations and employ different default character encodings:
Out-File
/ >
/ Set-Content
/ Add-Content
all act culture-sensitively, i.e., they produce representations suitable for the current culture (locale), if available (though custom formatting data is free to define its own, culture-invariant representation - see Get-Help about_format.ps1xml
).
This contrasts with PowerShell's string expansion (string interpolation in double-quoted strings), which is culture-invariant - see this answer of mine.
As for performance: Since Set-Content
doesn't have to apply default formatting to its input, it performs better.
As for the OP's symptom with Add-Content
:
Since $env:COMPUTERNAME
cannot contain non-ASCII characters, Add-Content
's output, using "ANSI" encoding, should not result in ?
characters in the output, and the likeliest explanation is that the ?
were part of the preexisting content in output file $file
, which Add-Content
appended to.
Your sample code seems to be OK. Thus, the root problem needs to be dug up somehow. Let's eliminate chance for typos in the script. First off, make sure you put Set-Strictmode -Version 2.0
in the beginning of your script. This will help you to catch misspelled variable names. Like so,
# Test.ps1
set-strictmode -version 2.0 # Comment this line and no error will be reported.
$foo = "bar"
set-content -path ./test.txt -value $fo # Error! Should be "$foo"
PS C:\temp> .\test.ps1
The variable '$fo' cannot be retrieved because it has not been set.
At C:\temp\test.ps1:3 char:40
+ set-content -path ./test.txt -value $fo <<<<
+ CategoryInfo : InvalidOperation: (fo:Token) [], RuntimeException
+ FullyQualifiedErrorId : VariableIsUndefined
The next part about question marks sounds like you have a problem with Unicode. What's the output when you type the file with Powershell like so,
$file = "\\server\share\file.txt"
cat $file