New-PSSession creates a persistent PowerShell session on a local or remote computer. Unlike a one-time connection, the session can be reused across multiple commands and passed to Invoke-Command. section 5.1.3
Use persistent sessions to structure reliable remote automation:
- Create one session per target, then pass the successful sessions as an array to Invoke-Command for parallel execution. section 5.1.3 section 5.3.3
- Use try/catch with -ErrorAction Stop so failed connections are excluded from the session collection and recorded separately. section 5.3.3
- Remove sessions after execution because they remain active on both the local client and remote server. section 5.3.3
- For SSH remoting, select -HostName and -UserName instead of -ComputerName and -Credential; retain the same Invoke-Command workflow. section 5.4.4
Build a reusable multi-server control script
A control script can iterate through Svr01, Svr02, and Svr03, create sessions with New-PSSession, add only successful connections to a typed list, run a local script through Invoke-Command, collect results, and export connection errors. A port check can choose WSMan on 5985 or SSH on 22 before creating each session. section 5.3.3 section 5.4.4
$s = "localhost"
try{
$session = New-PSSession -ComputerName $s -ErrorAction Stop
$Sessions.Add($session)
}
catch{
Write-Host "$($s) failed to connect: $($_)"
}
Shows the essential failure-safe pattern: stop on connection errors, add only successful sessions, and report the failed target. section 5.3.3
Listing 5.2 Executing local script against remote computers using WSMan remoting
$servers = 'Svr01', 'Svr02', 'Svr03' #1
$CsvFile = 'P:\Scripts\VSCodeExtensions.csv' #2
$ScriptFile = 'P:\Scripts\Get-VSCodeExtensions.ps1' #3
$ConnectionErrors = "P:\Scripts\VSCodeErrors.csv" #4
if (Test-Path -Path $CsvFile) { #5
$csvData = Import-Csv -Path $CsvFile |
Select-Object -ExpandProperty PSComputerName -Unique
$servers = $servers | Where-Object { $_ -notin $csvData }
}
[System.Collections.Generic.List[PSObject]] $Sessions = @()
foreach ($s in $servers) { #6
$PSSession = @{
ComputerName = $s
}
try {
$session = New-PSSession @PSSession -ErrorAction Stop
$Sessions.Add($session)
}
catch {
[pscustomobject]@{ #7
ComputerName = $s
Date = Get-Date
ErrorMsg = $_
} | Export-Csv -Path $ConnectionErrors -Append
}
}
$Command = @{ #8
Session = $Sessions
FilePath = $ScriptFile
}
$Results = Invoke-Command @Command
$Results | Export-Csv -Path $CsvFile -Append #9
Remove-PSSession -Session $Sessions #10
Provides a reusable WSMan control-script structure with target filtering, persistent session creation, result collection, and cleanup. section 5.3.3
Listing 5.3 Remote execution using WSMan and SSH
$SshUser = 'posh' #1
$servers = 'Svr01', 'Svr02', 'Svr03' #2
$CsvFile = 'P:\Scripts\VSCodeExtensions.csv'
$ScriptFile = 'P:\Scripts\Get-VSCodeExtensions.ps1'
$ConnectionErrors = "P:\Scripts\VSCodeErrors.csv"
if (Test-Path -Path $CsvFile) {
$csvData = Import-Csv -Path $CsvFile |
Select-Object -ExpandProperty PSComputerName -Unique
$servers = $servers | Where-Object { $_ -notin $csvData }
}
[System.Collections.Generic.List[PSObject]] $Sessions = @()
foreach ($s in $servers) {
$test = @{ #3
ComputerName = $s
InformationLevel = 'Quiet'
WarningAction = 'SilentlyContinue'
}
try {
$PSSession = @{ #4
ErrorAction = 'Stop'
}
if (Test-NetConnection @test -Port 5985) { #5
$PSSession.Add('ComputerName', $s)
}
elseif (Test-NetConnection @test -Port 22) { #6
$PSSession.Add('HostName', $s)
$PSSession.Add('UserName', $SshUser)
}
else { #7
throw "connection test failed"
}
$session = New-PSSession @PSSession #8
$Sessions.Add($session)
}
catch {
[pscustomobject]@{
ComputerName = $s
Date = Get-Date
ErrorMsg = $_
} | Export-Csv -Path $ConnectionErrors -Append
}
}
$Command = @{ #9
Session = $Sessions
FilePath = $ScriptFile
}
$Results = Invoke-Command @Command
$Results | Export-Csv -Path $CsvFile -Append
Remove-PSSession -Session $Sessions
Extends the control-script pattern to choose between WSMan and SSH connections while preserving the command-execution workflow. section 5.4.4
