PowerShell Remote Management
PowerShell Remoting allows commands and scripts to run on remote computers over a network. Instead of physically sitting at each machine, an administrator can manage hundreds of servers from a single PowerShell session. Remoting is built on the WS-Management protocol (WinRM) and works across Windows, Linux, and macOS in PowerShell 7.
How PowerShell Remoting Works
Local Computer Remote Computer +--------------+ +----------------+ | PowerShell | --- Network --> | WinRM Service | | (Client) | WS-Management | (Listener) | | | | | | Invoke-Cmd | | Runs commands | | | <-- Results ---- | Returns output | +--------------+ +----------------+
Enabling PowerShell Remoting
Remoting must be enabled on the target (remote) computer. Run this command as Administrator on the remote machine:
# Enable PowerShell Remoting (run on target computer as Admin)
Enable-PSRemoting -Force
This command starts the WinRM service, sets it to start automatically, and creates a firewall rule to allow incoming connections.
# Verify WinRM is running
Get-Service WinRM
# Check the WinRM configuration
winrm quickconfig
Testing the Connection
# Test if a remote computer accepts remoting connections
Test-WSMan -ComputerName "Server01"
# Test with credentials
$cred = Get-Credential
Test-WSMan -ComputerName "Server01" -Credential $cred
Invoke-Command – Run Commands Remotely
Invoke-Command runs a script block on one or more remote computers and returns the results.
Run on a Single Remote Computer
# Run a command on Server01
Invoke-Command -ComputerName "Server01" -ScriptBlock {
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5
}
Run with Credentials
$cred = Get-Credential # Prompts for username and password
Invoke-Command -ComputerName "Server01" -Credential $cred -ScriptBlock {
Get-Service | Where-Object { $_.Status -eq "Stopped" }
}
Run on Multiple Computers Simultaneously
$servers = @("Web01", "DB01", "Cache01", "Mail01")
Invoke-Command -ComputerName $servers -ScriptBlock {
[PSCustomObject]@{
Computer = $env:COMPUTERNAME
FreeGBDisk = [math]::Round((Get-PSDrive C).Free / 1GB, 2)
CPULoad = (Get-CimInstance Win32_Processor).LoadPercentage
}
}
Output:
Computer FreeGBDisk CPULoad
-------- ---------- -------
Web01 45.30 12
DB01 92.10 5
Cache01 18.40 30
Mail01 67.20 8
Pass Local Variables to Remote Session
Local variables do not automatically exist inside a remote script block. Use the $Using: prefix to pass them.
$logPath = "C:\Logs\app.log"
$maxLines = 50
Invoke-Command -ComputerName "Server01" -ScriptBlock {
Get-Content -Path $Using:logPath -Tail $Using:maxLines
}
Enter-PSSession – Interactive Remote Session
Enter-PSSession opens an interactive remote shell — like SSH into a Windows server. Every command typed runs on the remote machine.
# Start interactive session
Enter-PSSession -ComputerName "Server01"
# Prompt changes to show remote machine
[Server01]: PS C:\Users\Admin> Get-Process
# Exit the remote session
Exit-PSSession
[Server01]: PS C:\Users\Admin>
|
Prompt shows you are inside the remote computer
Persistent Sessions with New-PSSession
A persistent session maintains the connection and preserves state (variables, imported modules) between multiple Invoke-Command calls. This avoids the overhead of creating a new connection for each command.
# Create a persistent session
$session = New-PSSession -ComputerName "Server01"
# Run multiple commands in the same session
Invoke-Command -Session $session -ScriptBlock {
$data = Get-ChildItem "C:\Logs"
}
Invoke-Command -Session $session -ScriptBlock {
Write-Host "Files found: $($data.Count)" # $data persists in the session
}
# Close the session when done
Remove-PSSession -Session $session
Reuse Session for Multiple Servers
$servers = @("Web01", "DB01", "Cache01")
$sessions = New-PSSession -ComputerName $servers
# Run a command on all sessions at once
Invoke-Command -Session $sessions -ScriptBlock {
Restart-Service -Name "wuauserv" -Force
Write-Host "$env:COMPUTERNAME – Service restarted"
}
# Close all sessions
$sessions | Remove-PSSession
Copy Files to and from Remote Computers
$session = New-PSSession -ComputerName "Server01"
# Copy from local to remote
Copy-Item -Path "C:\Scripts\deploy.ps1" `
-Destination "C:\Scripts\" `
-ToSession $session
# Copy from remote to local
Copy-Item -Path "C:\Logs\app.log" `
-Destination "C:\LocalLogs\" `
-FromSession $session
Remove-PSSession $session
PowerShell Remoting over SSH (PowerShell 7)
PowerShell 7 supports remoting over SSH, which enables cross-platform management — connecting from Windows to Linux or macOS.
# Connect to a Linux server over SSH
Enter-PSSession -HostName "linuxserver01" -UserName "admin"
# Run a command on a Linux server
Invoke-Command -HostName "linuxserver01" -UserName "admin" -ScriptBlock {
uname -a
Get-Process | Select-Object -First 5
}
# Connect using SSH key (no password prompt)
Invoke-Command -HostName "linuxserver01" -UserName "admin" `
-KeyFilePath "~/.ssh/id_rsa" -ScriptBlock {
hostname
}
WinRM Configuration and Trusted Hosts
When connecting to computers in a workgroup (not domain-joined), the remote computer's name or IP must be added to the TrustedHosts list on the local machine.
# Add a specific computer to trusted hosts
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "Server01"
# Add multiple computers
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "Server01,Server02,192.168.1.*"
# Add all computers (use cautiously)
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*"
# View current trusted hosts
Get-Item WSMan:\localhost\Client\TrustedHosts
HTTPS Remoting (Secure)
# Enable HTTPS listener (requires a certificate)
# On remote server – create a listener on port 5986
New-WSManInstance -ResourceURI winrm/config/Listener `
-SelectorSet @{Address="*"; Transport="HTTPS"} `
-ValueSet @{CertificateThumbprint="YOUR_CERT_THUMBPRINT"}
# Connect using HTTPS from client
$options = New-PSSessionOption -SkipCNCheck -SkipCACheck
Enter-PSSession -ComputerName "Server01" -UseSSL -SessionOption $options
Real-World Example – Health Check Across All Servers
$servers = @("Web01", "DB01", "AppServer01", "FileServer01")
$cred = Get-Credential
$report = Invoke-Command -ComputerName $servers -Credential $cred -ScriptBlock {
$disk = Get-PSDrive C
$cpu = (Get-CimInstance Win32_Processor).LoadPercentage
$ram = Get-CimInstance Win32_OperatingSystem
$ramFreeGB = [math]::Round($ram.FreePhysicalMemory / 1MB, 2)
[PSCustomObject]@{
Server = $env:COMPUTERNAME
DiskFreeGB = [math]::Round($disk.Free / 1GB, 2)
CPUPercent = $cpu
RAMFreeGB = $ramFreeGB
Status = if ($cpu -gt 90 -or $disk.Free/1GB -lt 5) { "ALERT" } else { "OK" }
}
}
$report | Sort-Object Status -Descending | Format-Table -AutoSize
Summary
PowerShell Remoting transforms single-machine management into multi-server automation. Invoke-Command runs commands or script blocks on remote computers simultaneously. Enter-PSSession opens an interactive shell on a remote machine. Persistent sessions with New-PSSession preserve state and reduce connection overhead across multiple commands. Copy-Item with session objects transfers files to and from remote systems. PowerShell 7 adds SSH-based remoting for cross-platform Linux and macOS management. Remoting is the foundation of enterprise-scale PowerShell automation.
