How to log output of imported PowerShell module to a log file

129 views Asked by At

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?

1

There are 1 answers

1
mklement0 On BEST ANSWER

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
    
    • However, if you request a (separate) stderr redirection (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:

      • UTF-16LE ("Unicode") in Windows PowerShell.
      • BOM-less UTF-8 in PowerShell (Core) 7+ (BOM-less UTF-8 is the consistent default there).
      • To choose a different encoding, use Out-File explicitly, with its -Encoding parameter (but then you cannot combine it with Tee-Object).
    • Tee-Object with -FilePath uses:

      • UTF-16LE ("Unicode"), invariably in Windows PowerShell
      • BOM-less UTF-8 in PowerShell (Core) 7+ by default; in v7.3+, the -Encoding parameter can be used to change that.
    • Start-Object with -RedirectStandardOutput and -RedirectStandardOutput:

      • Invariably uses the console window's output code page (see below).
  • 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.

      • This means that for full Unicode support you'll have to switch the calling console window to UTF-8 first (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.