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
