Our friends over at the Scripting Guy Blog have an incredible write up on PowerShell 2.0 remoting which contains excerpts from the book Windows PowerShell 2.0 Best Practices by Ed Wilson


Hey, Scripting Guy! Question

Hey, Scripting Guy! I have heard that remoting is one of the cool new features of Windows PowerShell 2.0. What are the remoting features in Windows PowerShell 2.0, and how should I use them?

— FL

Hey, Scripting Guy! AnswerHello FL,

Microsoft Scripting Guy Ed Wilson here. I spent yesterday evening crawling around in my attic re-doing my telephone lines. I wanted to move my ADSL router to the other side of my office, and there was not a telephone line there. In addition, I wanted to add a couple of new Ethernet ports to my premises wiring to get ready for my new computer that will be arriving in a few days. It reminded me of when I was just starting out as a computer dude, way back before VBScript was even invented. It was kind of cool getting out my fox and hound, my multimeter, my punch-down tools, and clogging my lungs with insulation. Something bordering on the nostalgic I imagine. The bad thing about doing those sorts of installation jobs at home is that you have to clean up after yourself a little better than you might if you were at work, especially at my house because the Scripting Wife does not cut any slack.

Speaking of nostalgic, I remember back in the day when if you wanted to run a command on a remote computer, you either had to get up out of your chair and go to the computer and type in the command, or get someone on the phone who could type the command for you. There was no centralized management and not much in the way of remote access either. Ah, the good old days! Like 300 baud modems and spending all day to download a single file—no, thank you. Sometimes good old days are best left in the past. I prefer to live in the present, or even the near future. With the release of Windows 7 and Windows PowerShell 2.0, the near future has arrived!

Remote PowerShell Session

When you have a series of commands you need to enter, or you have some work you need to accomplish on a remote server or workstation, a remote interactive session is the remote tool you will need to use. A remote interactive session turns the Windows PowerShell session on your machine into a Windows PowerShell session on a remote machine. All commands you type are executed as if they were typed on the console of the remote computer.

Be careful with path commands in a remote interactive session—they resolve to the remote computer. This can be very confusing at first.

You are allowed to have only one remote interactive session running from your Windows PowerShell console. It is permissible, however, to have multiple Windows PowerShell consoles open, and for each to have a remote interactive session running. To begin an interactive Windows PowerShell session, you use the Enter-PSSession cmdlet. You do not need to rely upon pass-through authentication because the cmdlet supports the parameter. This syntax is illustrated here:

Enter-PSSession -ComputerName Berlin -Credential nwtraders/administrator

To create a remote Windows PowerShell session, you use the New-PsSession cmdlet. The use of New-PsSession and Enter-PsSession are illustrated here.

PS C:> New-PSSession -Name server1Test -ComputerName server1
Id Name ComputerName State ConfigurationName Availability
— —- ———— —– —————– ————
4 server1Test server1 Opened Microsoft.PowerShell Available
PS C:> Enter-PSSession -Name server1Test
[server1]: PS C:Usersadministrator.NWTRADERSDocuments> hostname
[server1]: PS C:Usersadministrator.NWTRADERSDocuments> gwmi win32_operatingsystem
SystemDirectory : C:Windowssystem32
Organization :
BuildNumber : 7600
RegisteredUser : Windows User
SerialNumber : 00486-001-0001076-84399
Version : 6.1.7600
[server1]: PS C:Usersadministrator.NWTRADERSDocuments> exit
PS C:> gwmi win32_operatingsystem
SystemDirectory : C:Windowssystem32
Organization :
BuildNumber : 7600
RegisteredUser : win7
SerialNumber : 00392-918-5000002-85015
Version : 6.1.7600
PS C:>

Remote command execution

If you only have a couple of commands you wish to execute on the remote computer, you can use the Invoke-Command cmdlet. When using the Invoke-Command cmdlet, a remote connection is established on the remote computer, the command executed, data returned to the originating computer, and the connection broken. A subsequent command to the remote computer would create a new temporary connection in the same manner as the first. There is no persistent connection, data, or shared state between the connections. In the code below, we execute the Get-Host cmdlet on a remote server named berlin. You will see that the results from berlin are returned to the host computer:

PS C:> Invoke-Command -ComputerName berlin -ScriptBlock { get-host }
Name : ServerRemoteHost
Version :
InstanceId : 4bef95fc-7ee4-4be6-93b8-be7ea9ed3757
UI : System.Management.Automation.Internal.Host.InternalHostUserInterf
CurrentCulture : en-US
CurrentUICulture : en-US
PrivateData :
PSComputerName : berlin

Persistent connection

If you wish to run a series of commands on multiple computers and maintain the ability to share data between the commands, you will need to first make a persistent connection prior to using the Invoke-Command cmdlet. To create the persistent session, use the New-PsSession cmdlet and specify the name of the computer. You will need to save the returned connection object in a variable. You then use this connection when running the remote command. In the example here, we first establish a persistent session with a computer named berlin. We store the returned session object in a variable named $session. Next we use the session parameter when using the Invoke-Command cmdlet to run two commands. The first command uses the Get-Command cmdlet to get a collection of commands from the remote computer. It stores those command objects into a variable named $a. In the next command, we continue to use the persistent connection, and this time we share the $a variable between the running of the two commands. We pass the objects contained in the $a variable to the Get-Help cmdlet. This code is seen here:

$session = New-PSSession -ComputerName berlin
Invoke-Command -Session $session -ScriptBlock { $a = Get-Command }
Invoke-Command -Session $session -ScriptBlock { $a | get-help }

As seen in the following image, you cannot use the session name that was created earlier in our example. This is because the session name is a string, and the –session parameter wants to receive a session object. If you attempt to use the session name from an earlier command, you will receive an error that states that Windows PowerShell cannot bind the –session parameter to a string. After a new session object is created, the Invoke-Command cmdlet can be used to run a command on a remote computer. This is seen here:

Image of error message

Remote script execution

If you have a script you need to execute on a remote computer, but the script is stored locally on your host machine, in the past you would have had to physically copy the script to the remote computer, and then use something like the create method from Win32_Process to execute remote computer. In Windows PowerShell 2.0, we can use the Invoke-Command cmdlet to execute a script that is stored locally and have it run on a remote computer. When the script is run, the results of the script are returned to the local computer. In the example shown here, we use the Invoke-Command cmdlet to run a script called getBios.ps1 on a remote computer named berlin. The filepath parameter is used to tell the Invoke-Command cmdlet where to find the script. This path must resolve locally.

PS C:> Invoke-Command -ComputerName berlin -FilePath C:fsogetBios.ps1
SMBIOSBIOSVersion : 080002
Manufacturer : American Megatrends Inc.
Name : BIOS Date: 02/22/06 20:54:49 Ver: 08.00.02
SerialNumber : 2096-1160-0447-0846-3027-2471-99
Version : A M I – 2000622
PSComputerName : berlin

As a best practice, use a remote interactive session when you wish to perform multiple commands on a single remote computer. If you have one or two commands that you wish to run on multiple remote computers, use remote command execution. If you have multiple commands you wish to execute on multiple computers, use a persistent connection. If you need to run a script that does not exist on a remote computer, use remote script execution.

Well, FL, that is about it for a quick overview of remoting in Windows PowerShell. Join us tomorrow when we dive into our virtual mail bag and respond to a bunch of questions requiring relatively short answers. It is time for Quick-Hits Friday.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, keep on scripting!