Learn PowerShell - PowerShell Remoting
Episode 14 of 31

Learn PowerShell - PowerShell Remoting

Managing many computers from one place: understand WinRM and TrustedHosts, enter interactively with Enter-PSSession, run bulk commands with Invoke-Command and parallel execution, leverage persistent sessions, secure with authentication and JEA, and cross-platform remoting via SSH.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Introduction

In episode 13 you organized commands into modules — code is organized, but still limited to one computer. The real world isn't like that: an administrator manages dozens of servers, and turning on RDP one by one then typing commands repeatedly is an unjustifiable waste of time.

This episode covers PowerShell Remoting: running commands on other computers as if you were sitting in front of them. You'll learn the basics of WinRM, the interactive Enter-PSSession session, bulk execution with Invoke-Command and parallelism, persistent sessions, authentication security and JEA, and cross-platform SSH-based remoting.

Basic Concepts: WinRM and WSMan

Remoting on Windows uses WinRM (Windows Remote Management), an implementation of the WSMan protocol. Simply put: your computer sends a web-service-based request to the target computer, and the target executes it. Enabling is done once on the target computer, as an administrator:

Enable WinRM on the target computer
Enable-PSRemoting -Force

Enable-PSRemoting configures the WinRM service, opens the firewall, and creates the default session endpoint. Once active, test the connection with Test-WSMan:

Test WinRM connection to target
Test-WSMan -ComputerName server-web-01

The output shows the protocol version and product. If it fails, the cause is usually the firewall, the WinRM service being stopped, or a TrustedHosts configuration issue, covered next.

TrustedHosts

WinRM doesn't accept credentials from just any computer. In a workgroup environment (not a domain), the target must register the sending computer in the TrustedHosts list:

Adding a computer to TrustedHosts
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "server-web-01" -Force

TrustedHosts is a list of allowed names or IPs. The value * means trusting all computers — never use it in a real environment. In a domain using Kerberos, TrustedHosts usually doesn't need changing because authentication is already trusted.

One-to-One: Enter-PSSession and Exit-PSSession

Enter-PSSession opens an interactive shell on the remote computer — like "RDP for the command line": the prompt changes and every command you type runs on the target computer.

Enter an interactive remote session
Enter-PSSession -ComputerName server-web-01

After entering, the prompt changes to [server-web-01]: PS C:\>. All commands run on that server. Exit with:

Exit the remote session
Exit-PSSession

Enter-PSSession is convenient for exploration and manual debugging. For automation — running commands from a script — use Invoke-Command.

One-to-Many: Invoke-Command

Invoke-Command runs a script block on one or many computers at once and collects the results. This is the main tool of remote automation.

Run a command on several servers
Invoke-Command -ComputerName server-web-01, server-web-02 -ScriptBlock {
    Get-Service -Name W3SVC | Select-Object Status, Name
}

Each computer's result is labeled with PSComputerName so you know which result belongs to which server. Analogy: Enter-PSSession is like visiting one store and asking directly; Invoke-Command is like sending a questionnaire to many stores at once and reading all the answers in one stack.

An important pattern: local variables are brought to the remote via -ArgumentList — variables inside the script block are interpreted on the target side, not on your computer.

Sending parameters to a script block
$service = "W3SVC"
Invoke-Command -ComputerName server-web-01 -ArgumentList $service -ScriptBlock {
    param($serviceName)
    Restart-Service -Name $serviceName
}

Parallel Execution

Running commands to 50 servers one by one is very slow. -ThrottleLimit controls how many concurrent connections happen. PowerShell 7 adds the -Parallel parameter to run script blocks in parallel within one ForEach-Object:

Parallel execution in PowerShell 7
$servers = Get-Content ./servers.txt
$servers | ForEach-Object -Parallel {
    Test-WSMan -ComputerName $_ | Select-Object ProductVersion
} -ThrottleLimit 10

-ThrottleLimit 10 limits concurrent connections so the network isn't flooded. Parallel doesn't mean unlimited — manage with throttle according to your infrastructure's capacity.

Persistent Sessions: New-PSSession

Every time Invoke-Command finishes, the remote session is closed. For work that needs state — loading modules, building configuration on the target, then using it again — create a persistent session with New-PSSession. The session survives and can be reused.

Persistent session lifecycle
$session = New-PSSession -ComputerName server-web-01
Invoke-Command -Session $session -ScriptBlock { $PSVersionTable.PSVersion }
Get-PSSession
Remove-PSSession -Session $session

The lifecycle: create with New-PSSession (once, expensive), reuse repeatedly with -Session, check which are still active with Get-PSSession, then clean up with Remove-PSSession so resources don't hang on the target. Sessions forgotten to be removed will pile up — check routinely with Get-PSSession and clear the unused ones.

Implicit Remoting with Import-PSSession

Import-PSSession takes the command list from a remote session and creates local versions of them — as if the remote cmdlets run directly on your computer. This is called implicit remoting, and is very useful for modules that only exist on the server.

Bring server module cmdlets to local
$session = New-PSSession -ComputerName dc-01
Import-PSSession -Session $session -Module ActiveDirectory
Get-ADUser -Identity arman
Remove-PSSession -Session $session

After Import-PSSession, Get-ADUser is available locally even though the ActiveDirectory module isn't installed on your computer. Behind the scenes, every call is forwarded to the remote session. Caution: imported commands are temporary and removed once the session closes.

Session Configurations and JEA

Default WinRM creates a session endpoint giving full PowerShell access. For production environments, restrict it with a session configuration — a special endpoint with its own rules:

Registering a restricted session endpoint
Register-PSSessionConfiguration -Name LimitedShell `
    -SessionType RestrictedRemoteServer -Force

RestrictedRemoteServer creates a highly restricted shell: only a few core commands, no access to dangerous functions. A more advanced endpoint is called JEA (Just Enough Administration) — the concept of granting the least privileges possible: non-admin users are given roles that only run certain commands. JEA requires role capability files and an endpoint mapping roles to groups.

Note

JEA is the pinnacle of remoting security practice: not "users can log in and do everything", but "users can only do what their role allows". When audits demand who did what on production servers, JEA is the answer.

Authentication Security

WinRM supports several authentication schemes. Default is Kerberos in domains and Negotiate in workgroups. For alternative credentials use -Credential:

Authentication with explicit credentials
$cred = Get-Credential
Invoke-Command -ComputerName server-web-01 -Credential $cred -ScriptBlock { Get-Date }

CredSSP allows credential delegation to a second layer — needed when a remote calls another remote. But CredSSP sends credentials to a server that could be abused if the server is compromised. Use it only when necessary and avoid it on untrusted networks. A safer alternative is certificate authentication — an X.509 certificate replaces the password. For transport, HTTPS encrypts all communication; its setup requires a certificate on the target computer and a WinRM service configured on port 5986.

Important

Basic authentication sends credentials almost plaintext. Only use it together with HTTPS — and better yet, avoid it entirely in favor of Kerberos or certificate authentication. Sending passwords unencrypted over a network is an invitation for credential theft.

SSH Remoting (PowerShell 7+)

Starting with PowerShell 7, remoting also runs over SSH — the same protocol Linux uses. Its advantages: cross-platform (Windows, Linux, macOS) and no WinRM needed. The concepts are the same: Enter-PSSession or Invoke-Command with the -HostName and -UserName parameters.

SSH remoting in PowerShell 7
Enter-PSSession -HostName ubuntu-dev-01 -UserName arman
Invoke-Command via SSH
Invoke-Command -HostName ubuntu-dev-01 -UserName arman -ScriptBlock { uname -a }

The requirements: both machines have SSH active, and PowerShell is installed on the remote machine. SSH sessions don't support all WinRM features (for example persistent sessions via -Session), so choose the transport by need: WinRM for Windows-to-Windows with full features, SSH for cross-platform.

Conclusion

This episode turns a single administrator seat into central control: understanding WinRM and WSMan as the foundation, enabling remoting and managing TrustedHosts, exploring interactively with Enter-PSSession, running bulk commands with Invoke-Command and parallel execution, using persistent New-PSSession sessions plus implicit remoting, securing with proper authentication and JEA, and cross-platform SSH-based remoting.

Key takeaways:

  • Enable-PSRemoting prepares the target; Test-WSMan verifies the connection.
  • Enter-PSSession for interactive; Invoke-Command for bulk automation.
  • Local variables come in via -ArgumentList; -ThrottleLimit for parallelism.
  • Persistent sessions are cleaned up with Remove-PSSession.
  • JEA restricts roles, not just who can log in.
  • SSH remoting for cross-platform in PowerShell 7.

Remoting gives you control over many computers. Episode 15 shifts focus to what runs inside those computers: Working with Services & Processes — managing services, processes, scheduled tasks, and reading event logs. See you in episode 15!

Learn PowerShell - PowerShell Remoting | Learn PowerShell