I have a PowerShell Script that is importing a module and I am calling this module. However, this module has lots of useful output that I am not capturing and I would like to write it to a file. What is the best way to do this?
Example code:
Write-Host "Loading modules.." -ForegroundColor Cyan
Import-Module C:\Users\Dev1\Downloads\WimConvertTest\WindowsImageTools\private\cleanupFile.ps1
Import-Module C:\Users\Dev1\Downloads\WimConvertTest\WindowsImageTools\private\Get-FullFilePath.ps1
Import-Module C:\Users\Dev1\Downloads\WimConvertTest\WindowsImageTools\private\Initialize-DiskPartition.ps1
Import-Module C:\Users\Dev1\Downloads\WimConvertTest\WindowsImageTools\private\Initialize-VHDPartition.ps1
Import-Module C:\Users\Dev1\Downloads\WimConvertTest\WindowsImageTools\private\MountVHDandRunBlock.ps1
Import-Module C:\Users\Dev1\Downloads\WimConvertTest\WindowsImageTools\private\New-TemporaryDirectory.ps1
Import-Module C:\Users\Dev1\Downloads\WimConvertTest\WindowsImageTools\private\Run-Executable.ps1
Import-Module C:\Users\Dev1\Downloads\WimConvertTest\WindowsImageTools\private\Set-DiskPartition.ps1
Import-Module C:\Users\Dev1\Downloads\WimConvertTest\WindowsImageTools\private\Set-VHDPartition.ps1
Import-Module C:\Users\Dev1\Downloads\WimConvertTest\WindowsImageTools\private\Wim2VhdClass.ps1
Import-Module C:\Users\Dev1\Downloads\WimConvertTest\WindowsImageTools\private\cleanupFile.ps1
Import-Module C:\Users\Dev1\Downloads\WimConvertTest\WindowsImageTools\Public\Convert-Wim2VHD.ps1
try
{
Write-Host "========================== Creating VHDX ================================== "
Convert-WIM2VHD -Path ".\os_1.vhdx" -SourcePath ".\os_1.wim" -Size 16GB -force -DiskLayout UEFI
# How to send output from imported module to a "_Convert-WIM2VHD.log"
# Example: powershell -Command "Start-Process 'powershell.exe' -Wait -ArgumentList '-ExecutionPolicy Bypass -Command \"...?
}
catch
{
Write-Host $Error[0]
Write-Host $Error[0].Exception.GetType().FullName
What is the best way to get all the output from Convert-WIM2VHD to _Convert-WIM2VHD.log?
How to send output from imported module to a "_Convert-WIM2VHD.log"
From inside PowerShell:
To capture output only in a file, use a redirection: to capture output from all PowerShell output streams, use *>
Convert-WIM2VHD ... *> _Convert-WIM2VHD.log
To also capture output in a file, while still outputting it (to the success output stream, which prints to the display by default), use Tee-Object
; combine with a *>&1
redirection in order to capture all streams:[1]
Convert-WIM2VHD ... *>&1 | Tee-Object -FilePath _Convert-WIM2VHD.log
To also capture output from an entire script or session, use Start-Transcript
and Stop-Transcript
:
Start-Transcript _Convert-WIM2VHD.log
# ... commands or script calls whose output to capture
# You can also build these calls into your script.
Stop-Transcript
In a Start-Process
call, the only way to capture any output is in files, namely via -RedirectStandardOutput
and -RedirectStandardError
, but note:
There's usually no reason to use Start-Process
to invoke console applications - see this answer; GitHub docs issue #6239 provides guidance on when use of Start-Process
is and isn't appropriate.
Capturing combined stdout and stderr output isn't directly possible, though when calling the PowerShell CLI, specifically, even PowerShell error output is sent to stdout (see below). For other programs, you'd have to call via a shell (such as PowerShell) in order to merge the streams - see this answer.
From outside PowerShell, when calling the the PowerShell CLI (powershell.exe
for Windows PowerShell, pwsh
for PowerShell (Core) 7+):
Because the PowerShell CLI sends all its output streams to stdout - including the error stream - a simple >
redirection from a calling shell (e.g. cmd.exe
, Bash) is sufficient; e.g.:
powershell -NoProfile -ExecutionPolicy Bypass -Command '...' > _Convert-WIM2VHD.log
2>
), PowerShell's error stream is sent to stderr (but none of the other non-sucesss streams).Note: While this send-everything-to-stdout-by-default behavior happens to be convenient for this use case, it is generally problematic: arguably, all streams other than the success output stream should be sent to stderr - see GitHub issue #7989.
Character-encoding considerations, i.e. what character encoding is used in the output files:
From inside PowerShell:
>
, as an effective alias of Out-File
, uses the latter's default encoding:
Out-File
explicitly, with its -Encoding
parameter (but then you cannot combine it with Tee-Object
).Tee-Object
with -FilePath
uses:
-Encoding
parameter can be used to change that.Start-Object
with -RedirectStandardOutput
and -RedirectStandardOutput
:
From outside PowerShell:
On Windows, the PowerShell CLI (in both editions) uses the console window's output code page (as reported by chcp
), which defaults to the system's active legacy OEM code page, such as 437
on US-English systems.
chcp 65001
); since Windows 10 it is also possible to configure a system to use UTF-8 system-wide, in which case both the OEM and the ANSI code page are set to 65001
(UTF-8). However, this has far-reaching consequences in that it can change the behavior of existing console applications and PowerShell scripts; see this answer for details as well as a PowerShell-only alternative.Un Unix-like systems, the PowerShell CLI (pwsh
, the PowerShell (Core) CLI) invariably outputs (BOM-less) UTF-8-encoded text.
[1] Note that this by design merges all streams into the success output stream (which is what makes it possible for Tee-Object
to see all output) and therefore "pollutes" the latter; for display output that doesn't matter, however.