PowerShell V2 Remoting - a first glimpse

With PowerShell V2, you can do more with less, and remoting is among one of the most important innovations. It actually integrates tightly with other features such as jobs, security and throttling, but today, I want to focus on Remoting only and give you some inspiration and ideas.

Microsoft PowerShell MVPs Tobias, Dmitry, MOW at the Ask-the-Experts Booth at TechEd EMEA in Barcelona

Note: This blog series is based entirely on notes I hastily took while listening to Jeffrey Snovers public presentations in Barcelona. I did not verify the code bits I published here (because then I would have had to use NDA bits). Don't necessarily expect them to run flawlessly or even being complete. They do give you a great idea of what Remoting is and how it works. Feel free to comment and correct anything you discover. In December with the CTP3 publicly available, we then can all play with the real bits.

Back to the story. Here's the mission: PowerShell scripts should do more with less. Specifically, they should run locally or remotely, synchroneously or asynchroneously in the background, against single or multiple machines, using wide ranges of authentication and protocols.

Please welcome: PSSession!

The mother of all remoting is something called a "PSSession", which is an environment where PowerShell can exist. You do not necessarily need to care about PSSessions as PowerShell creates them automatically if you don't. Let's start with some V1-compatible local code:

$script = {get-process p*}
Invoke-Command $script

Here, the variable $script contains an executable piece of code (a so called script block) which lists all processes starting with "p". So, where is the magic?

Executing Stuff Remotely

There is none. Not yet. The magic comes with the new -ComputerName parameter that was added to many cmdlets. With just a few changes, the same code gets executed on a remote machine instead of your local box:

$cred = Get-Credential Administrator
Invoke-Command -ComputerName 'testserver1' -Cred $cred -Auth Basic $script

$cred takes your credentials, and then Invoke-Command invokes the script code on the machine you specified using the credentials you submitted.

In this last example, PowerShell has automagically created a PSSession on the remote computer. Your PowerShell then connected to the remote session and executed your code. You can almost "feel" PowerShell create the remote PSSession because there is an initial lag when you start executing code remotely - which is precisely when the remote Session is created.

Preserving Sessions

This lag is good because it reminds you that you can optimize things and provide a remote session yourself, thus keeping the remote session around so next time you need to execute something on that machine, it goes a lot quicker.

# Create a new Remote Session:
$s = New-PSSession -computername 'Testserver' -Cred $cred -Auth Basic

# Use the session as often as needed to execute code on that machine:
icm $s $script

"Icm" is the alias for Invoke-Command, and this Cmdlet has two positional parameters: a session and a script block. So in this example, I first manually create my session using New-PSSession and then, since I have a handle on that session, can reuse it throughout all following tasks.

Executing PS-Scripts Remotely

A slight variant executes entire PowerShell Scripts remotely. All you do is exchange the script block with the -filename parameter and specify a PS1 script you have access to. PowerShell then reads that file, converts its content into a script block and runs your file remotely - no need to copy the script to the remote machine.

Since -Computername really can take an array of names (thus enabling you to run against hundreds or thousands of systems simultaneously), and since the command transmits the script you want to run to the target machines automatically, this truly is a bright new wonder world for distributed automation. By the way: To list all Cmdlets that actually have a -ComputerName parameter, do this:

Get-Help * -Parameter ComputerName 

Another remarkable tech fact is this: the remoting uses WS-Man which in turn does not depend on old-fashioned RPC/DCOM but instead flexibly works over a variety of protocols like HTTPS/HTTP on port 80, traversing firewalls and other network barriers. Thus you can manage even tricky locked down DMZs this way (which immediately raises tons of security-related questions that will be addressed in a different blog post, rest assured the PS team invested a lot of thought into that as well):

icm -Computername 'server1','server2','server7' -filepath .\manageserver.ps1

"Remote Desktop for Consoles"

While Invoke-Command runs single commands against any PSSession, local or remote, you can also turn your entire PowerShell console into a remote session. It's really a bit like Remote Desktop for Consoles.

Enter-PSSession -computername den-core-01

This will create a new remote Session on the computer you specified and then redirect all console I/O. Your console is still on your computer, of course, but what you see and do is actually happening on the remote system. Of course, with this interactive approach you can connect only to one remote system at a  time.

Once you are done, don't forget to clean up behind you:

Get-PSSession | Remove-PSSession

Mobile Object Model

One important aspect of remoting deals with the object nature of PowerShell. As you probably know, PowerShell works with rich objects. However, rich objects cannot be beamed to another universe. The technology simply isn't there, yet. So whenever you connect to a remote system, you do not get back the objects you expect. They still look and feel like objects but in reality, they are "deserialized" copies. Essentially, what that means is: they are read-only. No writable properties, no methods. You simply get back a "ghost" representation of the actual live remote object. Microsoft calls this Mobile Object Model.

In reality, the deserialized object does have writable properties but they are worthless because the deserialized object is no longer connected to the original object. Changing properties would only change your local copy of the object but would not do anything to the real object. It is a bit like ADSI objects without SetInfo(), or generally put, there is no way to play back the changes made to a deserialized object.

This sounds worse than it is because those read-only copies work fine for sorting, filtering and presenting data. You just can't change things. If you wanted that, you would simply have to avoid to beam the objects to your local machine but instead do all code on the remote system.

Managing Heterogeneous Worlds (aka "what about Unix?")

Finally, since Remoting uses a service called WS-Man, and since there is an open implementation available called OpenWSMan, PowerShells' remoting architecture principally also supports non-Windows systems like Unix and Linux. More on that later.

Let the PowerShell be with you!

-Tobias

PowerShellPlus


Posted Nov 06 2008, 07:29 PM by Tobias Weltner
Concentrated Tech NSoftware Dell Compellent Sponsored by Idera and Concentrated Tech and NSoftware and Dell Compellent
Copyright 2011 PowerShell.com. All rights reserved.