Windows PowerShellA Sneak Peek at Remote Management in Version 2.0

Don Jones

This column is based on a prerelease version of Windows PowerShell. All information herein is subject to change.


Two Types of Remoting
Synchronous vs. Asynchronous
Reusable Runspaces
Fan-In Remoting
The Killer App in 2.0

Have you had a chance to experiment with the latest Community Technology Preview (CTP) of Windows PowerShell 2.0? The latest version, CTP2, has further refined remote management, and right now is a great time to start becoming familiar with the new capabilities it offers. Before I get started here, you should take a moment to

download it from

First, let me clarify a couple of important points. A CTP is pre-beta code that Microsoft provides to let eager users like me get an idea of where Microsoft is headed with the next version of an application. Each CTP milestone or drop (as they call it in the industry) may differ completely from previous drops. This is because the development team gathers feedback, reviews it carefully, and then makes changes to the application based on this user feedback. That methodology brings up an important benefit and an important caveat about your use of the CTP.

Video (no longer available)

Watch Don Jones demonstrate the new remote management capabilities in Windows PowerShell 2.0 CTP2.

The benefit is that when you use the CTP, you're able to give feedback (through the Web site) about the product at a time during the development when the team is able to act on that feedback! If you wait until the beta or, even worse, Release Candidate stage, your feedback is a lot harder to incorporate. During CTP, anything might happen and the team can make vast and sweeping changes, if necessary.

That brings me to the caveat. The CTP is not ready for production. Sure, Windows PowerShell™ 2.0 CTP2 may be one of the most stable pieces of pre-release code you've seen, but keep in mind that the next CTP drop may be a completely different app. So don't start relying on CTP2, because the next version may require you to start all over.

Note that the CTP can't be installed in parallel with Windows PowerShell 1.0. For an ideal setup, the system should also have the Microsoft® .NET Framework 3.5 installed to enable all the available features. Otherwise, some features will be limited.

In addition, since the CTP is very early code, Microsoft has so far placed the most emphasis on the app working on the latest operating systems, meaning Windows Vista® and Windows Server® 2008. Current OS compatibility is no indication of the OS compatibility you can expect for the final released code. Backporting receives attention later in the development cycle.

Two Types of Remoting

In the world of remote management, you usually find two types of remoting: fan-in and fan-out. Fan-in remoting encompasses multiple administrators making secure shell connections to a single server. Windows PowerShell is designed to enable this in a secure, partitioned manner so that, for example, an Exchange Server hosting company can provide its customers with administrative access to their portions of a server. With fan-in remoting, you get secure, remote, interactive access to the copy of Windows PowerShell (version 2.0 only!) installed on a remote server.

Fan-out remoting is when you issue a set of commands to an entire group of remote servers at once. The commands "fan out" from your workstation to the group of servers in parallel. The commands execute on each server, and the results—in the form of Windows PowerShell objects—are returned to your workstation so you can review and work with them. Windows PowerShell supports two core technologies for fan-out remoting—Windows® Management Instrumentation (WMI) and Windows Remote Management (WinRM), which first shipped with Windows Server 2008 and was then updated in the Windows PowerShell 2.0 CTP.

Synchronous vs. Asynchronous

Actually, even Windows PowerShell 1.0 had some basic fan-out capabilities, which were tied to WMI. For example, you could easily create an array of computer names and then retrieve a WMI class from each:

$names = @("server1","server2","server2") Get-WmiObject Win32_OperatingSystem –computer $names

Executing methods—such as rebooting a computer—required a bit more work since version 1.0 offered no bulk way to execute WMI methods. That has changed, however, in the version 2.0 CTP thanks to the Invoke-WmiMethod cmdlet:

$names = @("server1","server2","server2") Get-WmiObject Win32_OperatingSystem –computer $names | ` Invoke-WmiMethod Reboot

There is a problem with this technique, though. It's synchronous, which means each computer is contacted one at a time, and you have to wait for each to finish before you can execute other commands. But the CTP introduces a new concept—background jobs—that allows commands like this to execute in the background. At its simplest, you can have a WMI command run in the background by simply adding the –AsJob parameter:

$names = @("server1","server2","server2") Get-WmiObject Win32_OperatingSystem –computer $names -asjob

You can review the resulting job's status by running Get-PSJob, and you can view the final results of the job by running Receive-PSJob. (I'll look at more of the details behind job management in a future column.) However, the Invoke-Command cmdlet provides an even better means of running commands in the background, like so:

$command = { Get-WmiObject Win32_OperatingSystem } $names = @("server1","server2","server2") Invoke-Command –command $command –computer $names –asjob

This actually pushes the Get-WmiObject command out to each specified computer, and it then executes locally. It typically executes much faster and without having to rely on the WMI remote procedure call (RPC) connections. Instead, Invoke-Command utilizes WinRM, which by default uses port 80 or 443. These ports make it easy to navigate firewalls and are entirely configurable. Invoke-Command also supports additional parameters for alternate credentials and throttling, allowing you to target hundreds of computers but have only a handful running in parallel. This allows you to avoid congestion and excess overhead.

Reusable Runspaces

If you plan to remotely manage a given set of computers more than once, you should consider using runspaces rather than simple lists of computer names. In Windows PowerShell, a runspace is simply an instance of the shell's engine, whether it's running locally on your computer as the shell console window or running in the background on a remote computer. Starting a remote runspace is easy:

$names = @("server1","server2","server2") New-RunSpace –computer $names

As runspaces also use WinRM, they also use port 80 (or 443, if you specify the –UseSSL parameter) by default. They can also accept alternate credentials, and so on. If you retrieve the resulting runspace objects, you can pass them to Invoke-Command, and Windows PowerShell will push the command out to the computers on which those runspaces exist:

$command = { Get-WmiObject Win32_OperatingSystem } $rs = Get-Runspace Invoke-Command –command $command –runspace $rs –asjob

The benefit here is that the runspaces remain active for as long as the shell is open, so you can simply reuse them for additional commands.

Fan-In Remoting

Runspaces are also the key to fan-in remoting. For example, Figure 1 shows that I've created a runspace on a remote computer, retrieved a reference to that runspace, and then used the Push-Runspace cmdlet to activate the runspace. At that point, I'm running commands on the remote computer, much like SSH or other remote-shell utilities would allow. Running Pop-Runspace brings back my original, "local" runspace, and the shell prompt helps me keep track of where I am at any moment.


Figure 1 Using runspace to run commands on a remote computer (Click the image for a larger view)

The exact sequence of commands I ran is as follows:

PS C:\>new-runspace -computer "WIN-YFZXQMHXAWM" PS C:\>$server2 = get-runspace -sessionid 2 PS C:\>push-runspace $server2 [win-yfzxqmhxawm]: PS C:\Windows\System32> pop-runspace PS C:\>

This technique is called fan-in because multiple admins can open remote interactive runspaces on the same server at the same time—they "fan in" from their individual workstations to the server. A new security model in Windows PowerShell 2.0 allows you to create restricted shells and cmdlets, so each admin can be prevented from making global modifications. Each is limited to his own area of the shell. (These new security techniques require some custom software development in a .NET Framework-targeted language. This is beyond the scope of the Windows PowerShell column, but it is nice to know these capabilities exist.)

The Killer App in 2.0

The Windows PowerShell 2.0 CTP has a stunning list of new features. In my opinion, remoting is the killer app. Every administrator in nearly any environment can benefit from it.

You should familiarize yourself with these features so you can offer your suggestions to the product team. Do you want WinRM default ports to be managed via Group Policy? Should the cmdlets work differently? Are there performance issues? Is WinRM easy enough to configure? You can make an impact by sending suggestions to or share your feedback with MVP Award recipients, including me (to reach me, post your feedback to the forums on So get involved, and help build the killer app for the next generation of Windows PowerShell!

Cmdlet of the Month: Select-Object

Try this out: Get-Service | ConvertTo-HTML | Out-File Services.htm. Now check out the resulting HTML file in your Web browser. There's quite a lot of information, isn't there? If only there was a way to trim it down a bit by selecting the information you are interested in. That is exactly what Select-Object can do for you. For instance, say you just want a list of service names and their current status. You can use this: Get-Service | Select Name,Status | ConvertTo-HTML | Out-File Services.htm.

One thing you need to remember, though, is that Select-Object discards the original object—in this case, services—and produces a custom object (literally a PSCustom object type) that contains only the properties you've specified. Any functionality of the original object is no longer accessible, so you'll likely want to keep Select-Object near the end of your pipeline, working with the original object for as long as you can.

Don Jones is coauthor of Windows PowerShell v2.0: TFM and the trainer behind "Special Forces" classroom training ( You can reach him at

© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; reproduction in part or in whole without permission is prohibited.