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.

Leave a Comment