PowerShell Remoting
PowerShell Remoting enables you to run commands on remote computers using WS-Management (WinRM) protocol.
Basic Remoting Setup
Enabling Remoting
# Enable remoting on local machine (admin required)
Enable-PSRemoting -Force
# Verify remoting status
Get-PSSessionConfiguration
# Configure trusted hosts
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*" -Force # For testing only
Restart-Service WinRM
Basic Remote Commands
# One-time command execution
Invoke-Command -ComputerName "Server01" -ScriptBlock { Get-Service }
# Multiple computers
$servers = "Server01", "Server02", "Server03"
Invoke-Command -ComputerName $servers -ScriptBlock { Get-Process }
# With credentials
$cred = Get-Credential
Invoke-Command -ComputerName "Server01" -Credential $cred -ScriptBlock {
Get-ChildItem "C:\Important"
}
Persistent Sessions
# Create persistent session
$session = New-PSSession -ComputerName "Server01" -Credential $cred
# Use existing session
Invoke-Command -Session $session -ScriptBlock { Get-EventLog -LogName System -Newest 10 }
# Interactive session
Enter-PSSession -ComputerName "Server01" # Exit with 'exit' command
# Multiple sessions
$sessions = New-PSSession -ComputerName $servers -Credential $cred
Invoke-Command -Session $sessions -ScriptBlock { Get-Service }
Advanced Remoting Techniques
Passing Local Variables
$localVar = "ImportantData"
Invoke-Command -ComputerName "Server01" -ScriptBlock {
param($data)
"Received: $data"
} -ArgumentList $localVar
Returning Complex Objects
$results = Invoke-Command -ComputerName "Server01" -ScriptBlock {
Get-Process | Select-Object Name, CPU, Id
}
# Process results locally
$results | Where-Object { $_.CPU -gt 100 } | Sort-Object CPU -Descending
Throttling and Parallel Execution
# Throttle concurrent connections
Invoke-Command -ComputerName $servers -ScriptBlock {
Get-Service
} -ThrottleLimit 10
# Asynchronous execution
$jobs = Invoke-Command -ComputerName $servers -ScriptBlock {
Start-Sleep -Seconds 10
"Done"
} -AsJob
# Monitor jobs
$jobs | Receive-Job -Wait
Implicit Remoting
# Import remote commands locally
$session = New-PSSession -ComputerName "ExchangeServer"
Import-PSSession -Session $session -Module "Exchange" -Prefix "Remote"
# Use imported commands
Get-RemoteMailbox -Identity "user@domain.com"
Security Considerations
# Configure HTTPS listener
$cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.Subject -match "Server01" }
New-PSWSManInstance -Name "PSRemoting" -CertificateThumbprint $cert.Thumbprint
# JEA (Just Enough Administration)
# Create role capability file
New-PSRoleCapabilityFile -Path ".\BasicUser.psrc" -VisibleCmdlets "Get-Service"
# Create session configuration
Register-PSSessionConfiguration -Name "BasicUser" -RoleDefinitions @{
"DOMAIN\BasicUsers" = @{ RoleCapabilities = "BasicUser" }
}
Troubleshooting Remoting
# Test connection
Test-WSMan -ComputerName "Server01"
# Check firewall rules
Get-NetFirewallRule -Name *WinRM*
# Enable logging
Set-WSManQuickConfig -LogLevel "Debug"
Cross-Platform Remoting
# Linux/macOS setup
# Install PowerShell and configure SSH
sudo apt install openssh-client openssh-server
sudo systemctl enable ssh
sudo systemctl start ssh
# Windows to Linux remoting
Enter-PSSession -HostName "linux-server" -UserName "admin" -SSHTransport
# Linux to Windows remoting
ssh admin@windows-server "powershell -Command { Get-Process }"
Practical Examples
Multi-Server Management
# Get disk space across servers
$diskReport = Invoke-Command -ComputerName $servers -ScriptBlock {
Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" |
Select-Object DeviceID,
@{Name="SizeGB";Expression={[math]::Round($_.Size/1GB,2)}},
@{Name="FreeGB";Expression={[math]::Round($_.FreeSpace/1GB,2)}}
}
$diskReport | Group-Object PSComputerName | Format-Table
Software Deployment
# Deploy software to multiple machines
Invoke-Command -ComputerName $servers -FilePath "C:\Scripts\DeploySoftware.ps1"
# Or with script block
$installScript = {
$tempFile = "C:\Temp\installer.msi"
Copy-Item -Path "\\fileshare\installer.msi" -Destination $tempFile
Start-Process -FilePath "msiexec.exe" -ArgumentList "/i $tempFile /quiet" -Wait
Remove-Item -Path $tempFile
}
Invoke-Command -ComputerName $servers -ScriptBlock $installScript
Configuration Management
# Ensure consistent configuration
Invoke-Command -ComputerName $servers -ScriptBlock {
# Set power plan
powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c # High performance
# Configure Windows Update
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" `
-Name "NoAutoUpdate" -Value 0
}