Windows Remote execution with Powershell and WinRM

A while back, I posted about using WinRM for automating tasks on remote Windows machines.
WinRM (Windows Remote Management) is Microsoft’s implementation of WS-Management, a SOAP based protocol for management of devices and servers. Among other things, it can be used to connect to remote Windows servers and run commands on them, similar to SSH in the Linux world.

In this post, I am going to show an actual example of using WinRM to execute commands on a remote machine using Powershell.

We’ll need two Windows hosts for this example, which we will start on the Amazon cloud.

Environment Setup

Let’s set up all of the resources we’ll need. I’ll use the EC2 CLI to set everything up. Of-course, if you already have two windows machine to use, you can skip this part.

  • Set up the security group

We will need to open two ports – 3389 for Remote Desktop access to the client machine, and 5985 for WinRM access to the server machine.

ec2-create-group -d “WinRM Group” WinRM-Group
ec2-authorize -P TCP -p 3389 -s 0.0.0.0/0 WinRM-Group
ec2-authorize -P TCP -p 5985 -s 0.0.0.0/0 WinRM-Group

  • Create the keypair for our test

ec2-create-keypair “WinRM-kp”

And save the created private key in a file named WinRM-kp.pem

  • Now let’s start the instances

ec2-run-instances ami-678c4c10 -n 2 -g “WinRM-Group” -k “WinRM-kp” -t “m1.medium”
INSTANCE i-37973874 ami-678c4c10 pending WinRM-kp 0 m1.medium 2014-06-24T07:44:51+0000 eu-west-1a windows monitoring-disabled ebs hvm xen sg-871a25f0 default false
INSTANCE i-36973875 ami-678c4c10 pending WinRM-kp 1 m1.medium 2014-06-24T07:44:51+0000 eu-west-1a windows monitoring-disabled ebs hvm xen sg-871a25f0 default false

Note the instance IDs, highlighted above. We’ll need them later.

For this example I have chosen to use Windows 2008 R2. The AMI ID is ami-678c4c10 at the time of writing this post, but may of-course change in the future.

I recommend adding the Name tag to the instances to make the API results and web console more readable:

ec2-create-tags i-37973874 -t Name=Client
ec2-create-tags i-36973875 -t Name=Server

Make sure to note the public DNS names of the new machines:

~$ec2-describe-instances i-37973874
INSTANCE i-37973874 ami-678c4c10 ec2-54-73-137-146.eu-west-1.compute.amazonaws.com … 
TAG instance i-37973874 Name Client
~$ ec2-describe-instances i-36973875
RESERVATION r-dde5109e 535075449278 WinRM-Group
INSTANCE i-36973875 ami-678c4c10 ec2-54-74-118-124.eu-west-1.compute.amazonaws.com …
TAG instance i-36973875 Name Server

  • Now we wait until the Windows passwords become available. This can take a few minutes:

ec2-get-password -k WinRM-kp.pem i-37973874
XXXXXXXX

ec2-get-password -k WinRM-kp.pem i-36973875
YYYYYYYY

WinRM in Action

OK, our environment is set up. First, lets RDPs (Remote Desktop) to the client machine.
Once on the client machine, we need to set up the client environment.
First, open a Powershell window.

  • Enable WinRM access to the remote machine

We need to tell Windows which remote hosts can be connected to.

Set-Item WSMan:localhostClientTrustedHosts -Value ec2-54-74-118-124.eu-west-1.compute.amazonaws.com -Force

Note that you can just allow access to any host with:

Set-Item WSMan:localhostClientTrustedHosts -Value * -Force

  • Enable script execution on the client:

Set-ExecutionPolicy -Force unrestricted

  • Create the Powershell credentials

You can create the credentials interactively, or with a script.
The interactive version brings up a windows pop-up where you enter your username and password:

$cred = Get-Credential

To skip the interactive bits and run everything automatically:

$securePassword = ConvertTo-SecureString -AsPlainText -Force ‘YYYYYYYY’
$cred = New-Object System.Management.Automation.PSCredential ‘Administrator’, $securePassword

  • And start you remote Powershell session

Enter-PSSession -ComputerName ec2-54-74-118-124.eu-west-1.compute.amazonaws.com -Credential $cred

That’s it. You now have a running remote session. Any command you run in this shell is in fact running on the remote machine.

Note that we did not make any changes to the server – you can just bring up a plain vanilla instance on EC2 and start working on it immediately.

Some Additional Useful Commands

  • Create a reusable session

New-PSSession -ComputerName ec2-54-74-118-124.eu-west-1.compute.amazonaws.com -Credential $cred
Id Name ComputerName State ConfigurationName Availability
— —— —————— ——- ————————- ——————
2 Session2 ec2-54-74-11… Opened Microsoft.PowerShell Available

Enter-PSSession 2

Creating a session like this lets you open multiple sessions and go back and forth among them without having to open a new session each time.

  • List Open sessions

Get-PSSession

  • Close a Session

Remove-PSSession 2

  • Remote execute a command

Invoke-Command -ComputerName ec2-54-74-118-124.eu-west-1.compute.amazonaws.com -Credential $cred -ScriptBlock {dir}

Really useful for executing that one-line command on the server.

  • Remote execute a script file

Invoke-Command -ComputerName ec2-54-74-118-124.eu-west-1.compute.amazonaws.com -Credential $cred .pathtoscript.ps1

Environment Cleanup

  • Undo client side changes

If you are keeping the client machine, you may want to remove the server from the Trusted Hosts list:

Set-Item WSMan:localhostClientTrustedHosts “”

  • EC2 Cleanup

Let’s clean up all of the resources:

ec2-terminate-instances i-37973874 i-36973875

ec2-delete-group WinRM-Group

ec2-delete-keypair WinRM-kp

Not using EC2?

Your windows server just needs to have WinRM installed and enabled. WinRM is usually available on any reasonably up to date Windows server. To enable WinRM you need to run one command:

Enable-PSRemoting -Force

Make sure port 5985 is allowed on whatever firewall system you are using.