Windows PowerShell Remoting

Just in case you have a computer or two that isn’t located in your office.


According to the old joke, the three most important things in real estate are location, location, location. And in Windows PowerShell 2.0 the three most important things are –


Well, to tell, you the truth, we don’t actually know what the three most important things are in Windows PowerShell 2.0. What we do know is that the three most important things in Windows PowerShell 2.0 are not location, location, location; that’s because location doesn’t matter in Windows PowerShell 2.0. Not in the least. (Well, except with profiles. But we’re not talking about profiles right now.)


Admittedly, that wasn’t the case with the original release of Windows PowerShell; in PowerShell 1.0 location – or, to be more specific – your location – was extremely important. That’s because Windows PowerShell 1.0 did not support (except in one or two minor instances) the concept of remoting, the ability for you to sit at computer A and retrieve information from, or make changes to, computer B. The only way for you to retrieve information from computer B was to physically sit at computer B. The idea of sitting at your desk and managing all your computers simply by transmitting commands across the network? As they say in New York, fuhhgeddaboutit.


Note. If you’re not from New York, that can be translated like this: forget about it.


Now, that might not have been all that bad except for one thing: Windows PowerShell was being promoted as the tool for system administration. System administration that could only be done locally, and only on one computer at a time. As they say in New York –


Well, you’re right: they say a lot of things in New York, don’t they? Never mind.


But that was then and this is, um, not then. With Windows PowerShell 2.0 you can now sit at computer A and manage computer B; for that matter, you can also manage computers C, D, E, F, and G. Remoting is now a real and viable part of Windows PowerShell; in fact, PowerShell now features three different ways to manage remote computers:


        By using .NET remoting. A handful of Windows PowerShell cmdlets (including Get- Service and Get-Event) harness the remoting capabilities built into the .NET Framework; that means that you can use these cmdlets to directly return data from a remote computer. (As opposed to making a transient or persistent connection.)

        By making a transient connection to a remote computer. With a transient connection you make a temporary connection to a remote computer. How temporary is this connection? Very temporary: you make the connection, run a single command, and then the connection is automatically terminated.

        By making a persistent connection to a remote computer. With a persistent connection you make a connection to a remote computer and then that connection remains open until you explicitly close it. That means you can run as many commands as you like, without ever having to open a new connection.


In this article, we’ll give you a quick introduction to all three methods of managing remote computers.


What do I need in order to make these remote connections?


To tell you the truth, not much. Obviously you need Windows PowerShell 2.0. Or to be more precise, you need the Windows Management Framework, which includes Windows PowerShell 2.0, Windows Remote Management (WinRM) 2.0, and Background Intelligent Transfer Service (BITS) 4.0.


In addition, you’ll need version 2.0 of the .NET Framework; there’s a pretty good chance you already have this installed in your computer.


And keep in mind that this software not only needs to be installed on your computer, but it also needs to be installed on every computer that you want to be able to manage remotely. Do you want to be able to manage all your client computers using PowerShell 2.0? Then PowerShell 2.0, .NET 2.0, and WinRM must be installed on each of those client computers.


Oh, and did we mention that you need to be a local administrator on your computer and on each remote computer you try to connect to? Well, we should have, because that’s absolutely crucial.


How does remoting work?


In a nutshell, here’s how remoting works in Windows PowerShell 2.0. To begin with, you make a connection between your computer and a remote computer. You then type a command on your computer and that command is transmitted across the network to the remote computer. (In case you’re worried, don’t be: all these transmissions are encrypted and secure.) The command is then executed on the remote computer. Note, however, that the command runs “invisibly;” nothing happens on the remote computer to indicate that the computer is running a Windows PowerShell command. When the command completes, the output is converted to XML format and transmitted back to your computer. Your computer then converts that XML packet back into a Windows PowerShell object.


The fact that PowerShell remoting transmits XML (or, to be more specific, SOAP packets) explains why this type of remoting is considered firewall-friendly, and can be carried out across the Internet. Previous system administration tools relied on DCOM (distributed COM) in order to do remoting; with DCOM, objects are transmitted across the network. That’s a problem: by default, most firewalls are designed to block objects. However, most firewalls are configured to allow XML packets; thus PowerShell remoting can typically be used without additional firewall configuration, and without allowing potentially-unsafe objects onto your network.


Can we get started now?


OK, good point, maybe it is time to actually start doing something. Let’s start by taking a minute to discuss .NET remoting, a type of remoting that – as we noted – applies to only a few cmdlets.


Note. Which cmdlets? In general, cmdlets that support the -ComputerName parameter support .NET remoting. You can retrieve a list of cmdlets that support the -ComputerName parameter by typing the following command at the Windows PowerShell prompt and then pressing ENTER:


Get-Help * -Parameter ComputerName


By default, when you run a cmdlet like Get-Service you simply, well, run the cmdlet, like so:




Do that, and Get-Service will retrieve information about all the services running on the local computer:


Status   Name               DisplayName

------   ----               -----------

Stopped  Adobe LM Service   Adobe LM Service

Stopped  AdobeActiveFile... Adobe Active File Monitor V4

Stopped  Alerter            Alerter

Running  ALG                Application Layer Gateway Service

Running  Apple Mobile De... Apple Mobile Device

Stopped  AppMgmt            Application Management

Running  ASChannel          Local Communication Channel

Stopped  aspnet_state       ASP.NET State Service

Stopped  Ati HotKey Poller  Ati HotKey Poller

Running  AudioSrv           Windows Audio


That’s simple enough. But what if you want to run that command against a remote computer? As it turns out, that’s simple enough, too: you just add the -ComputerName parameter followed by the name (or the IP address, or the fully qualified domain name) of the remote computer. For example, this command returns information from the remote computer atl-ocs-001:


Get-Service –ComputerName atl-ocs-001


Run this command, and you’ll get back something similar to this:


Status   Name               DisplayName

------   ----               -----------

Stopped Adobe LM Service    Adobe LM Service

Stopped AdobeActiveFile...  Adobe Active File Monitor V4

Stopped Alerter             Alerter

Running ALG                 Application Layer Gateway Service

Running Apple Mobile De...  Apple Mobile Device

Stopped AppMgmt             Application Management

Running ASChannel           Local Communication Channel

Stopped aspnet_state        ASP.NET State Service

Stopped Ati HotKey Poller   Ati HotKey Poller

Running AudioSrv            Windows Audio


As you can see, the output – well, now that you mention it, the output does look a lot like the output we got when we ran Get-Service without the-ComputerName parameter, doesn’t it? There’s actually two reasons for that. For one, we are retrieving service information from the remote computer; needless to say, service information from one computer will always resemble service information from another computer. In addition to that, Get-Service typically suppresses the value of the MachineName property, a property that indicates which computer the service is running on. But that’s OK; we can use a command like this to ask Get-Service to show us just the values of the DisplayName and the MachineName properties:


Get-Service –ComputerName atl-ocs-001 | Select-Object DisplayName, MachineName


Now take a peek at what we get back:


DisplayName                             MachineName

-----------                             -----------

Adobe LM Service                        atl-ocs-001

Adobe Active File Monitor V4            atl-ocs-001

Alerter                                 atl-ocs-001

Application Layer Gateway Service       atl-ocs-001

Apple Mobile Device                     atl-ocs-001

Application Management                  atl-ocs-001

Local Communication Channel             atl-ocs-001

ASP.NET State Service                   atl-ocs-001

Ati HotKey Poller                       atl-ocs-001

Windows Audio                           atl-ocs-001

Background Intelligent Transfer Ser...  atl-ocs-001


Not bad, huh? Incidentally, you aren’t limited to passing just one machine name to the –ComputerName parameter. Want to retrieve service information from computers atl-ocs-001, atl-ocs-002, and atl-ocs-003? Then just ask Get-Service to retrieve service information from each of these three machines, separating the computer names with commas:


Get-Service –ComputerName atl-ocs-001,atl-ocs-002,atl-ocs-003

Skip to main content