PowerShell Invoke-Command vs Enter-PSSession: When to Use Each

Remote PowerShell has two modes: running a script block on one or many machines silently with Invoke-Command, or opening an interactive shell on a single machine with Enter-PSSession. Knowing when each is appropriate — and why PowerShell Invoke-Command vs Enter-PSSession is not really a competition — makes your remoting work faster and more scalable.
Quick Answer / TL;DR
Use Invoke-Command for scripted, automated, or multi-machine remote execution. Use Enter-PSSession for interactive troubleshooting on a single machine. Invoke-Command scales to hundreds of machines simultaneously; Enter-PSSession connects to exactly one.
Invoke-Command: Non-Interactive Script Execution
Invoke-Command sends a script block to one or more remote computers, executes it, and returns the results to the local session. The remote machine runs the code and sends back serialized objects. This is the right choice for automation, scheduled tasks, and any scenario where you do not need to interact with the remote machine directly.
# Run a script block on one remote machine
Invoke-Command -ComputerName server01 -ScriptBlock {
Get-Service | Where-Object Status -ne Running
}
# Run on multiple machines simultaneously
$servers = 'web01','web02','web03','db01'
Invoke-Command -ComputerName $servers -ScriptBlock {
[PSCustomObject]@{
Computer = $env:COMPUTERNAME
Uptime = (Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
DiskFree = [math]::Round((Get-PSDrive C).Free / 1GB, 2)
}
}
Enter-PSSession: Interactive Shell
Enter-PSSession opens an interactive shell on a single remote machine. Your PowerShell prompt changes to show the remote machine name. Every command you type runs on the remote machine. This is the right choice for hands-on troubleshooting when you need to explore interactively, run commands based on what you see, and navigate the remote file system.
# Open interactive session to a remote machine
Enter-PSSession -ComputerName server01
# Your prompt changes:
# [server01]: PS C:\> _
# Run commands interactively on the remote machine
[server01]: PS C:\> Get-Service | Where-Object Status -ne Running
[server01]: PS C:\> Get-EventLog -LogName Application -Newest 10
[server01]: PS C:\> Exit-PSSession # return to local session
Performance: Persistent Sessions vs One-Off
Each Invoke-Command call without a session creates and destroys a connection, which adds overhead for frequent calls. For scripts that make multiple remote calls to the same machine, create a persistent PSSession with New-PSSession and reuse it. This reduces connection setup time significantly for repetitive operations.
# Without persistent session: connection overhead on each call
Invoke-Command -ComputerName server01 -ScriptBlock { Get-Service } # overhead
Invoke-Command -ComputerName server01 -ScriptBlock { Get-Process } # overhead again
# With persistent session: connect once, reuse
$session = New-PSSession -ComputerName server01
Invoke-Command -Session $session -ScriptBlock { Get-Service } # fast
Invoke-Command -Session $session -ScriptBlock { Get-Process } # fast
Remove-PSSession $session # cleanup when done
# Enter-PSSession can also use a pre-built session
Enter-PSSession -Session $session
Passing Variables to Remote Commands
Variables defined in the local session are not automatically available inside Invoke-Command script blocks. Use the $using: scope modifier to pass local variable values into the remote script block.
# Local variable — not accessible in remote script block by default
$serviceName = 'W3SVC'
# WRONG: $serviceName is not defined on the remote machine
Invoke-Command -ComputerName server01 -ScriptBlock {
Get-Service $serviceName # error: $serviceName is null
}
# CORRECT: use $using: to pass the value
Invoke-Command -ComputerName server01 -ScriptBlock {
Get-Service $using:serviceName # works correctly
}
# Multiple variables
$logPath = 'C:\Logs'
$maxAge = 30
Invoke-Command -ComputerName server01 -ScriptBlock {
Get-ChildItem $using:logPath | Where-Object Age -gt $using:maxAge
}
Running the Same Script on Many Computers
Invoke-Command with multiple computer names runs the script block on all specified machines in parallel (throttled by -ThrottleLimit, default 32). Results from all machines are returned together with a PSComputerName property indicating which machine each result came from.
# Run on 10 servers simultaneously
$allServers = Get-ADComputer -Filter * | Select-Object -ExpandProperty Name
$diskReport = Invoke-Command -ComputerName $allServers -ThrottleLimit 20 -ScriptBlock {
Get-PSDrive -PSProvider FileSystem | Where-Object Name -eq 'C' |
Select-Object @{N='Computer';E={$env:COMPUTERNAME}},
@{N='FreeGB';E={[math]::Round($_.Free/1GB,1)}},
@{N='UsedGB';E={[math]::Round($_.Used/1GB,1)}}
} -ErrorAction SilentlyContinue
$diskReport | Sort-Object FreeGB | Format-Table -AutoSize
Decision Guide
- Invoke-Command: automation, scheduled tasks, multi-machine operations, scripted workflows, CI/CD pipelines, collecting data from many machines
- Enter-PSSession: interactive troubleshooting, exploring unknown system state, debugging, making ad-hoc changes while seeing the results immediately
- Persistent PSSession: scripts that make multiple calls to the same machine and need to minimize connection overhead
Common Errors and Fixes
- Enter-PSSession is single-machine — Invoke-Command is the multi-machine tool.
Enter-PSSessionaccepts only one computer name. For multi-machine operations, always useInvoke-Command -ComputerNamewith an array of names. Attempting to pass multiple computer names toEnter-PSSessionthrows an error. - Local variables need $using: in Invoke-Command script block. The most common
Invoke-Commanderror is a variable that is$nullinside the remote script block because it was defined locally. Check for$using:on every local variable reference inside a remote script block. This does not apply toEnter-PSSessionwhere you are literally typing in the remote session.
Related Cmdlets / See Also
Wrapping Up
Invoke-Command is the workhorse of PowerShell remoting — automated, scalable, and pipeline-friendly. Enter-PSSession is the interactive console for hands-on remote work. Use persistent PSSession objects when you need to make multiple calls to the same machine. Always use $using: to pass local variables into remote script blocks.


