In PowerShell, what does creating a session with New-PSSession give you that calling Invoke-Command -ComputerName repeatedly does not?
answer
- state between calls
- who owns the runspace lifetime
- setup cost paid once
- remember to close it
basics
~20 sNew-PSSession creates a persistent remote runspace you reuse across calls, so connection setup and authentication happen once and state such as variables and imported modules survives between commands. Each Invoke-Command -ComputerName call instead builds a throwaway session and tears it down.
solid answer
~50 s`Invoke-Command -ComputerName` is a one-shot: it opens a temporary session, runs your script block, returns the output, and destroys the session. Anything you set up — a variable, an imported module, a loaded assembly, a working directory — is gone by the next call, and every call pays the connection and authentication cost again. `New-PSSession` gives you a `PSSession` object representing a runspace that stays open; you pass it with `-Session` to as many `Invoke-Command` calls as you like, and you can also `Enter-PSSession -Session $s` to step into the same live state interactively. The trade is that it is now yours to manage: sessions consume resources and count against WinRM's per-user shell quotas, so you close them with `Remove-PSSession` (or let the connection idle-timeout kill them). Use a persistent session for multi-step work against the same host; use the one-shot for a single independent command.
code
powershell · 8 lines$s = New-PSSession -ComputerName Server01
try {
Invoke-Command -Session $s -ScriptBlock { $deployRoot = 'C:\apps' }
Invoke-Command -Session $s -ScriptBlock { Get-ChildItem $deployRoot | Select-Object Name }
}
finally {
Remove-PSSession $s
}go deeper
Know that -ComputerName makes a throwaway connection per call while New-PSSession keeps one open, and that you close it with Remove-PSSession when done.
Explain what persists in a session — variables, functions, imported modules, loaded assemblies, current location — and the costs: connection resources, per-user WinRM shell quotas, idle timeouts, and mandatory cleanup.
Show that you script it safely: create sessions once for multi-step fleet work, check session State before each phase, and clean up in a finally block so a failure mid-run does not leak runspaces onto production hosts.
Weigh connection reuse against blast radius and resource limits across a fleet: how many concurrent sessions your service account may hold, whether long-running work should be disconnected and collected later, and where a purpose-built orchestrator beats holding thousands of live runspaces.
## Two shapes of the same machinery Both forms end up running your code in a remote runspace. The difference is the lifetime of that runspace and who controls it. ```powershell # one-shot: temporary session created and destroyed per call Invoke-Command -ComputerName Server01 -ScriptBlock { $x = 42 } Invoke-Command -ComputerName Server01 -ScriptBlock { $x } # empty: different session # persistent: one runspace, many commands $s = New-PSSession -ComputerName Server01 Invoke-Command -Session $s -ScriptBlock { $x = 42 } Invoke-Command -Session $s -ScriptBlock { $x } # 42 Remove-PSSession $s ``` That second call returning `42` is the whole point: the session *is* the state. ## What persists Inside a persistent session you keep everything a PowerShell runspace normally has: variables, functions you defined, modules you imported, .NET assemblies you loaded, the current location, and the session's error history. This matters more than it first sounds. Importing a heavy module is often the slowest part of a remote task; doing it once per session instead of once per command changes a script's runtime materially. Multi-step workflows — set something up, check it, act on the result — are natural in a session and awkward without one, because with one-shots you must re-establish context in every script block. ## What it costs A persistent session is a real process-side resource on the remote machine and a live connection on yours. - **It must be cleaned up.** `Remove-PSSession $s` closes it. If you leak sessions in a loop over hundreds of hosts, you will hit limits. - **WinRM enforces per-user quotas** on how many concurrent shells a user may have, so leaked sessions eventually produce failures for *other* work by the same account, not just yours. - **Idle timeouts apply.** A session left alone eventually closes on its own; you can tune this with `New-PSSessionOption -IdleTimeout` and pass the result to `-SessionOption`. - **A broken session stays broken.** `Get-PSSession` shows `State` and `Availability`; a session whose state is not `Opened` will not run anything, and long-running scripts should check rather than assume. ## Sharing a session across cmdlets The `PSSession` object is not tied to `Invoke-Command`. The same `$s` can be used by: ```powershell Enter-PSSession -Session $s # step into the live state interactively Invoke-Command -Session $s -FilePath .\step2.ps1 Import-Module -PSSession $s -Name ActiveDirectory # implicit remoting into the same session ``` This is a genuinely useful workflow: automate the setup with `Invoke-Command`, then `Enter-PSSession` into the very same runspace to inspect what went wrong, with all the variables still populated. ## Sessions to many hosts `New-PSSession -ComputerName` accepts an array and returns one session per host. Passing that whole array to `-Session` gives you fan-out over reused connections, which is the efficient shape when you must run several successive steps across a fleet: ```powershell $sessions = New-PSSession -ComputerName $servers Invoke-Command -Session $sessions -ScriptBlock { Import-Module MyOps } Invoke-Command -Session $sessions -ScriptBlock { Invoke-MyOpsCheck } Remove-PSSession $sessions ``` ## Disconnect and reconnect WS-Man sessions support being disconnected and later reconnected: `Disconnect-PSSession` leaves the runspace running on the server without your client attached, and `Connect-PSSession` or `Receive-PSSession` picks it back up — even from a different client machine. That makes it possible to start something long-running, close your laptop, and collect the results later. It is a WS-Man capability; SSH-transport sessions do not offer it. ## Choosing Single independent command, or a fan-out where each host does one self-contained thing: use `-ComputerName` and let PowerShell manage the temporary session. Several dependent steps, expensive setup, interactive follow-up, or work you may want to disconnect from: create the session explicitly and clean it up in a `finally` block so a failure does not leak it.
- What happens if a script creates sessions in a loop and never calls Remove-PSSession?Each session holds a runspace on the remote host and counts against WinRM's per-user concurrent-shell quota, so after enough iterations new connections start failing — and they fail for anything else that account is doing, not just this script. Idle timeouts eventually reclaim them, but the correct pattern is to close sessions in a `finally` block.
- Can you attach interactively to a session you have been driving with Invoke-Command?Yes — `Enter-PSSession -Session $s` steps into the same runspace with all its state intact, so variables you set through earlier `Invoke-Command -Session` calls are still there. It is a strong debugging move: automate the setup, then walk into the live session to inspect what actually happened.
- What do Disconnect-PSSession and Connect-PSSession let you do?`Disconnect-PSSession` detaches your client while the runspace keeps running on the server, and `Connect-PSSession` (or `Receive-PSSession` to also collect output) reattaches later, potentially from a different machine. It suits long-running work you do not want tied to your console staying open. This is a WS-Man feature, not available over the SSH transport.
- How would you check whether a session you are holding is still usable?`Get-PSSession` (or inspecting the object) exposes `State` and `Availability`; only a session whose state is `Opened` will run commands. Long-lived automation should verify this before each phase and recreate the session rather than letting every subsequent `Invoke-Command` fail against a dead runspace.
saying these in an interview costs you the question
- Thinks variables set by one -ComputerName call persist to the next
- Believes sessions close themselves so cleanup is unnecessary
- Says a persistent session is only about speed, not state
- Assumes a PSSession only works with Invoke-Command
- Claims one session can serve many hosts at once