liveBook · Manning

Output stream

As explained in Practical Automation with PowerShell: Effective scripting from the console to the cloud

An output stream is the PowerShell pipeline channel that carries success-output objects from commands and functions.

The output stream carries the objects a PowerShell command, function, or script emits as success output. A function returns everything written to this stream, not merely a value following a return statement. That behavior matters when a function is part of a larger automation: unintended output can become unexpected input later in the pipeline or in an assigned variable. section 2.1.1 section 2.1.2

Design functions so their intended result is the only success output. Save the result in a clearly named variable and place that variable alone on the final line. This makes the return path visible during maintenance and avoids mixing result output with incidental command output inside conditions or other logic. section 2.1.2

Control output deliberately when building reusable automation:

  • Suppress incidental success output with Out-Null when a command performs work but its emitted object is not part of the function result. For example, creating a missing directory can otherwise add a directory object to the function's output. section 2.1.1
  • Use Write-Verbose for progress and diagnostic confirmation when CmdletBinding is enabled. Verbose messages can appear with -Verbose without being returned through the output stream. section 2.1.1
  • Treat return as a processing-control command as well as a way to emit a value. It can stop function execution, but it does not make earlier output disappear or guarantee a single returned value. section 2.1.2
  • Use Write-Output only with awareness that it writes to the same output stream and may imply, incorrectly, that it is the function's sole result. section 2.1.2

Returning an archive path without directory-creation noise

An archive-path function may create its destination directory when Test-Path shows it is absent. Pipe New-Item to Out-Null so that the newly created directory is not returned. Write a verbose message to confirm creation when needed, then place the completed ZIP-file path variable on the last line as the function's intended result. section 2.1.1 section 2.1.2

Remote execution follows the same rule: everything a remote script writes to the output stream returns to its control script. Return only the data needed, and include the machine name and date or time so collected results remain attributable across systems and repeated runs. When a search finds no data, return a structured indication that the script ran rather than leaving no record. section 5.2.1

Listing 5.1 Get-VSCodeExtensions.ps1
[System.Collections.Generic.List[PSObject]] $extensions = @()
if ($IsLinux) {                                                #1
    $homePath = '/home/'
}
else {
    $homePath = "$($env:HOMEDRIVE)\Users"
}
 
$homeDirs = Get-ChildItem -Path $homePath -Directory           #2
 
foreach ($dir in $homeDirs) {                                  #3
    $vscPath = Join-Path $dir.FullName '.vscode\extensions'
    if (Test-Path -Path $vscPath) {                            #4
        $ChildItem = @{
            Path    = $vscPath
            Recurse = $true
            Filter  = '.vsixmanifest'
            Force   = $true
        }
        $manifests = Get-ChildItem @ChildItem
        foreach ($m in $manifests) {
            [xml]$vsix = Get-Content -Path $m.FullName         #5
            $vsix.PackageManifest.Metadata.Identity |          #6
            Select-Object -Property Id, Version, Publisher,
            @{l = 'Folder'; e = { $m.FullName } },             #7
            @{l = 'ComputerName'; e = {[system.environment]::MachineName}},
            @{l = 'Date'; e = { Get-Date } } |
            ForEach-Object { $extensions.Add($_) }
        }
    }
}
if ($extensions.Count -eq 0) {                                 #8
    $extensions.Add([pscustomobject]@{
            Id           = 'No extension found'
            Version      = $null
            Publisher    = $null
            Folder       = $null
            ComputerName = [system.environment]::MachineName
            Date         = Get-Date
        })
}
$extensions                                                    #9

This extension-inventory script provides an operational case for collecting objects across user profiles; its remote results should be limited to the information the control script needs. section 5.2.1

How Practical Automation with PowerShell: Effective scripting from the console to the cloud covers it

How deep it goes
Explains output behavior through suppression, verbose diagnostics, final-variable returns, and remote-result design; it does not detail pipeline internals.
Examples
Uses archive-directory creation and a remote VS Code extension inventory to illustrate controlled returned data.
What it assumes
Assumes familiarity with PowerShell functions, cmdlets, variables, and conditional logic.
What you can do after
Apply it to make function and remote-script results predictable while retaining verbose diagnostics.
How it connects
Connects output streams with functions, Out-Null, Write-Verbose, Write-Output, return, and remote execution.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Practical Automation with PowerShell: Effective scripting from the console to the cloud. The section links point to the parts of the book it draws on.