Remoting Mental Model: PSRP, Transports, Sessions, and Serialization
Build the correct mental model for PowerShell remoting: PSRP over a transport, remote execution contexts, persistent sessions, serialization, variable capture, and bounded fan-out.
Learning objectives
- Distinguish PSRP, transport, endpoint, authentication, session, and serialization.
- Compare one-off Invoke-Command with persistent PSSession workflows.
- Explain why many remote objects become deserialized snapshots.
- Use $Using: and -ArgumentList with a clear data-boundary mental model.
- Preserve remote provenance such as PSComputerName.
- Describe fan-out and throttling before automating fleets.
1. Remote execution creates a second execution environment
When you run Get-Process locally, the command,
variables, modules, filesystem paths, permissions, and .NET objects
all belong to your current PowerShell process. Remoting changes that
model: a client asks another PowerShell process to run code
elsewhere and return a representation of the result.
The most important beginner habit is to ask,
“Which computer and which PowerShell process owns this
state?”
A path such as C:\Logs, a module name, or a variable
can mean something completely different on the remote host.
2. The remoting vocabulary describes separate responsibilities
| Term | Meaning |
|---|---|
| PSRP | The PowerShell Remoting Protocol: the PowerShell-level protocol that carries commands, streams, and serialized data. |
| Transport | The underlying connection mechanism. In modern PowerShell this is commonly WSMan between Windows systems or SSH across platforms. |
| Endpoint / session configuration | The remote PowerShell hosting configuration you connect to. WSMan supports named endpoint configurations; current SSH remoting uses an SSH subsystem and does not provide the same endpoint/JEA hosting model. |
| Authentication | How the remote side establishes who you are, such as Kerberos/Negotiate for Windows WSMan or SSH key/password mechanisms for SSH. |
| PSSession | A persistent logical remote PowerShell session that can retain remote variables and other session state between commands. |
| Serialization | Converting objects into transferable data so they can cross a process/network boundary. |
These layers are related but not interchangeable. SSH is not PSRP, and PSRP is not authentication. Keeping the layers separate makes troubleshooting much easier.
3. Mental model: command goes out, serialized data comes back
The transport carries PSRP traffic to a remote PowerShell host. The command runs there, then result objects and streams are serialized for the return trip.
flowchart TD A[Local PowerShell client] -->|PSRP messages| B[Transport: WSMan or SSH] B --> C[Remote PowerShell host] C --> D[Command executes with remote paths modules permissions] D --> E[Objects and streams] E -->|serialize| B B -->|deserialize| A
4. Temporary commands and persistent sessions solve different problems
Invoke-Command can create a temporary connection, run a
script block, return the result, and close that temporary session.
This is excellent for one-off read operations.
# Windows WSMan example -- requires a configured Windows target.
Invoke-Command -ComputerName 'server01' -ScriptBlock {
[pscustomobject]@{
Computer = $env:COMPUTERNAME
Edition = $PSVersionTable.PSEdition
Version = $PSVersionTable.PSVersion.ToString()
}
}
For a sequence of related commands, create a PSSession.
State created inside that remote session can be reused later.
$session = New-PSSession -ComputerName 'server01'
Invoke-Command -Session $session -ScriptBlock { $script:InventoryTag = 'batch-42' }
Invoke-Command -Session $session -ScriptBlock { $script:InventoryTag }
Remove-PSSession -Session $session
5. Most remote output is a snapshot, not a live remote object
Live .NET objects cannot simply move across the network with their
process-bound methods and handles intact. PowerShell serializes
object properties, sends the representation, then deserializes it
locally. Many complex values therefore arrive as
PSObject snapshots whose type names are prefixed with
Deserialized..
$remote = Invoke-Command -ComputerName 'server01' -ScriptBlock {
Get-Process -Id $PID
}
$remote.PSObject.TypeNames | Select-Object -First 3
$remote | Get-Member
You can filter, select, export, and inspect the returned properties.
But a process-specific method such as Kill() must
operate on the remote live process object inside the remote
command, not on a deserialized local snapshot.
6. Remote results carry provenance
PowerShell adds remoting metadata such as
PSComputerName and RunspaceId to many
results. Preserve that provenance when you are collecting from
multiple machines; it answers the critical question “which host
produced this record?”
Invoke-Command -ComputerName 'server01','server02' -ScriptBlock {
Get-Culture
} | Select-Object PSComputerName,Name,DisplayName
7. $Using: embeds a caller value into out-of-session code
A variable name inside a remote script block normally refers to a
variable in the remote session. Prefixing it with
Using: tells PowerShell to take the value from the
calling session and make that value available to the remote command.
$pattern = '*.log'
Invoke-Command -ComputerName 'server01' -ScriptBlock {
Get-ChildItem -Path $HOME -Filter $Using:pattern -File -ErrorAction SilentlyContinue |
Select-Object Name,Length
}
For remote and other out-of-process execution, that value crosses the boundary as an independent serialized copy. Assigning to a remote value does not mutate the original local variable.
8. Parameters make remote data flow easier to test
For larger script blocks, explicit parameters often make the
boundary clearer than many $Using: references.
-ArgumentList supplies local values to parameters
declared inside the remote script block.
$minimumMb = 512
Invoke-Command -ComputerName 'server01' -ScriptBlock {
param([int]$MinimumMb)
Get-Process |
Where-Object WorkingSet64 -ge ($MinimumMb * 1MB) |
Select-Object Name,Id,WorkingSet64
} -ArgumentList $minimumMb
9. Fan-out means one control point targets many remote systems
PowerShell can execute the same command against multiple targets.
That is fan-out. Concurrency must be bounded
because every remote connection consumes CPU, memory, sockets,
authentication work, and remote capacity.
-ThrottleLimit exists on relevant remoting commands to
cap concurrent work.
Do not interpret fan-out as an all-or-nothing transaction. Results can arrive in a different order than targets were listed, and one host can fail while others succeed.
10. Lab: model the boundary without requiring a second machine
If you do not have a remoting target, this lab uses a separate local PowerShell process to demonstrate the same core process boundary: data must be serialized, local variables are not shared, and returned values are copies.
$pwsh = (Get-Command pwsh -CommandType Application).Source
$payload = [pscustomobject]@{ Name='academy'; Count=3 }
$json = $payload | ConvertTo-Json -Compress
$previous = $env:ACADEMY_PAYLOAD
try {
$env:ACADEMY_PAYLOAD = $json
$result = & $pwsh -NoProfile -Command @'
$item = $env:ACADEMY_PAYLOAD | ConvertFrom-Json
[pscustomobject]@{
ProcessId = $PID
Name = $item.Name
Doubled = $item.Count * 2
} | ConvertTo-Json -Compress
'@
}
finally {
if ($null -eq $previous) { Remove-Item Env:ACADEMY_PAYLOAD -ErrorAction SilentlyContinue }
else { $env:ACADEMY_PAYLOAD = $previous }
}
$result | ConvertFrom-Json
The transport here is not PSRP, so it is not a remoting substitute. It is a safe demonstration of the fundamental boundary that remoting must also solve.
11. Verification checklist
- You can distinguish PSRP from WSMan and SSH.
-
You know when a one-off
Invoke-Commandis enough and when a PSSession is useful. - You expect remote complex objects to be serialized snapshots.
-
You preserve
PSComputerNamewhen collecting fleet data. -
You understand that
$Using:supplies a copied value to remote/out-of-process code. - You treat fan-out as bounded concurrent work with partial failure.
12. Common mistakes and why they fail
- Assuming a local path exists remotely: the remote process has its own filesystem and current directory.
- Calling methods on a deserialized object: many live methods were not transmitted.
- Expecting a remote assignment to change a local variable: out-of-process values are copied.
- Dropping target metadata: you lose the source of a fleet result.
- Opening unlimited connections: concurrency becomes a load problem instead of an automation feature.
13. Knowledge check
Question 1. What does PSRP provide?
Question 2. Why can a remote process object lose methods locally?
Question 3. When is a PSSession more useful than a one-off Invoke-Command?
Question 4. What does $Using:name mean in a remote command?
Question 5. Why keep PSComputerName in fleet output?
14. Summary and next bridge
Remoting is a boundary: code executes in another PowerShell host, reached through a transport, and data crosses via serialization. Once that model is clear, Windows WSMan configuration becomes easier to understand because listeners, authentication, endpoints, and trust are security controls around that boundary. Lesson 2 focuses on that Windows path.
15. Authoritative references
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.