Copy files to/from remote machine using PowerShell Remoting

It is easy to copy files from one network share to another. This can be done using either some kind of GUI tool or command line tool like PowerShell or robocopy. However you may not want to open SMB ports on a machine for obvious security reasons. More so is true of cloud hosted virtual machines.  In such a case, you can also copy files from your local machine to remote machine or vice versa using PowerShell remoting. In this blog post, we are going to discuss the steps to do the same.

Configure Remote machine for PowerShell Remoting

If you have PowerShell v3 installed on the remote machine, configuring it for PowerShell Remoting is easy. Just run below command on the administrative PowerShell window:

Enable-PSRemoting -Force -Verbose

The above cmdlet configures the winrm listener on the machine, configures firewall exception and starts winrm service. This allows winrm on the machine to start listening for the requests.

In case you have PowerShell v2 or less installed, you must run only winrm native commands to do listener configuration. In such a case, use below command on administrative command window:

winrm quickconfig

Add Certificate for WinRM configuration on remote machine

It’s generally not a good idea to use winrm commands over HTTP. So we’ll add a certificate to WinRM on the remote machine to add an extra layer of security. However, if you deem it unnecessary for your environment, you can skip this part.

First, we need to add an firewall exception on port 5986 (Winrm listens for HTTP requests on port 5985 and for HTTPS on 5986):

New-NetFirewallRule -Name "winrm_https" -DisplayName "winrm_https" -Enabled True -Profile Any -Action Allow -Direction Inbound -LocalPort 5986 -Protocol TCP

add windows firewall rule for winrm

After this, you’ll need to create a certificate for secure connection inside the machine. You may choose to use a publicly trusted certificate, but for our purposes we are using a self signed certificate as I just wanted to get up and running as quickly as possible. You need to provide a DNS name, later in the post we will connect via IP address and skip the DNS name check so it doesn’t actually matter what you set this to. However best practice would be to set this using DNS name.

For creating certificate, we can use a PowerShell command as below:

New-SelfSignedCertificate -DnsName {dns-name-of-the-machine} -CertStoreLocation Cert:\LocalMachine\My

add self signed certificate to machine

This will create a self signed certificate and add to local machine. Notice the thumbprint id created by using above command. To enable winrm on port 5986, we need to run below command (on a command prompt) inside virtual machine:

winrm create winrm/config/Listener?Address=*+Transport=HTTPS @{Hostname="{dns-name}"; CertificateThumbprint="{certificate-thumbprint}"}

Verify PSRemoting Works

For this, now we need to run below commands on client machine:

$so = New-PsSessionOption –SkipCACheck -SkipCNCheck
$creds = Get-Credential
Enter-PSSession -ComputerName {dns-name-of-remote-machine} -Credential $creds -UseSSL -SessionOption $so

You can navigate around to see whether or not you are successfully connected.

Copy file using PSRemoting

Now, first we need to create a new session to remote server and store it as a variable:

$so = New-PsSessionOption –SkipCACheck -SkipCNCheck
$creds = Get-Credential
$session = New-PSSession -ComputerName {dns-name-of-remote-machine} -Credential $creds -UseSSL -SessionOption $so

If we need to copy files from local machine to remote machine, we would need to use -ToSession parameter. For example:

Copy-Item "C:\temp\mail-script.ps1" -Destination "C:\Scripts\mail-script-new.ps1" -ToSession $session

The above command uses the Copy-Item cmdlet to copy mail-script from the C:\temp folder to the C:\Scripts folder on the remote computer using the session information stored in the $Session variable. As part of the copy operation, the command also changes the item name from mail-script.ps1 to mail-script-new.ps1, so it can be attached to email messages.

Similarly, when we need to copy files from remote machine to local machine, we can use -FromSession parameter. For example:

Copy-Item "C:\Scripts\mail-script.ps1" -Destination "C:\temp\mail-script-new.ps1" -FromSession $session

In above command, we copy the mail-script-new.ps1 from C:\Scripts folder on the remote machine to C:\temp folder on local machine and also rename it as mail-script.ps1.

Instead of copying individual files, we can also copy the whole directories as well. For example:

Copy-Item "C:\temp\backupscripts" -Destination "D:\Backups\scripts" -FromSession $Session

When operating on directories, it uses -Recurse parameter by default, so that subfolders along with their directory structure are also copied.

Happy Remoting.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s