Hey, Scripting Guy! Tell Me About Remoting in Windows PowerShell 2.0

Hey, Scripting Guy! Tell Me About Remoting in Windows PowerShell 2.0

  • Comments 10
  • Likes

Bookmark and Share

(Editor’s note: Portions of today's Hey, Scripting Guy! Blog post are excerpted from the Microsoft Press book, Windows PowerShell 2.0 Best Practices by Ed Wilson which is now available for pre-order.)

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:\Users\administrator.NWTRADERS\Documents> hostname
Server1
[server1]: PS C:\Users\administrator.NWTRADERS\Documents> gwmi win32_operatingsystem


SystemDirectory : C:\Windows\system32
Organization    :
BuildNumber     : 7600
RegisteredUser  : Windows User
SerialNumber    : 00486-001-0001076-84399
Version         : 6.1.7600



[server1]: PS C:\Users\administrator.NWTRADERS\Documents> exit
PS C:\> gwmi win32_operatingsystem


SystemDirectory : C:\Windows\system32
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          : 1.0.0.0
InstanceId       : 4bef95fc-7ee4-4be6-93b8-be7ea9ed3757
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterf
                   ace
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:\fso\getBios.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!

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Regarding the -FilePath parameter on Invoke-Command, must the full file path be explicitly defined?

    When executing Invoke-Command with a -FilePath parameter, PowerShell gives me an error saying it cannot find the file I specify. I am only specifying a file name, and the file is accessible via my path (as evidenced by the fact that I can dot-source the file using only the file name). Given that, why does Invoke-Command complain?

  • "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."

    Since telnet was invented in 1969, you must be really old!

  • Is 1969 considered to be really old? 1969 = 43 years old. It must truly be a near-death experience every day! :D

    80+ is old.

  • This PS remoting is a clunky joke compared to ssh on any other modern OS.

  • @Junior - I have to respond because you are comparing apples and mouse peas.

    WS-Remote and WSMan are industry standards (DMTF - Distributed Management Task Force) and are supported on nearly all OSs today including nearly all flavors of Linux.

    WSMan is managed and governed by an industry committee.  SSH can be run over WSMan.  SSH is not an industry standard and only works on custom installations.  It also is not designed to support remote management but is designed to create a shell for telnet and ftp sessions.  WSMan is a full cross-platform distributed management system.  WSMan is more robust and secure than SSH.

    SSH will be around for a bit until the distributed management tools are complete.

    See:

    blogs.technet.com/.../standards-based-management-in-windows-server-8.aspx

    blogs.msdn.com/.../standards-based-management-dmtf-management-profiles.aspx

    Here are the latest standards to wrap and extend CIM/WMI WSMan and WsRM:

    blogs.technet.com/.../open-management-infrastructure.aspx

    This extends interoperability to devices such as printers, phones, touch pads or any other device that needs to be managed.

    PowerShell and Windows 2012 (8) are moving full ahead into near complete standards compliance.  This will likely be the beginning of the end for all other remoting systems like SSH and remote console or WMI/DCOM.  All of these are not very reliable and lack cross-platform interoperability.

    SSH will be around for those cases where we still need to support legacy apps but will be pushed aside in high-security environments.

    Yes - SSH is simple but that simplicity also means it is very limited.  Many had tossed around the idea of enhancing the SSH concept.  It soon became clear that it would be far better to build a solution that was designed completely to new standards rather than kludging an old and somewhat worn out technology.

    One of the things I like most about PowerShell is its advanced remoting and promise to conform to standards.  It is also good that the base platform that PowerShell runs from, the Net Framework is fully supportive of PowerShell and standards.  It is not complete or perfect yet but we have come farther in the past two years than in all the previous years.

  • Hi Ed, could I ran a local MSI on a remote server this way as well?

  • well said jrv...

    you don't follow the standards and they complain...you do follow the standards and they complain...

    you cant please all the people all the time!

    I also appreciate the links you provided which gives a good baseline for people that "Don't get it"

  • I feel as though I've searched to the end of the Internet and can't find a way to start a Remote Powershell session in elevated mode.  I have a PS Script that uses commands that need to be run in Powershell "as admin"  Is this possible?

  • @At T

    There is never a need to start a remote session elevated.  In fact it is impossible to do this.  Elevation is only available to local sessions and is only required for local sessions.

  • While this holds a lot of promise, I'm confused.  Is it possible to utilize this without first either accessing the destination machine or creating a GPO to create a hole in the firewall for the winrm service?  I can verify that the service is running on the remote machine and in fact stop and start it but I can't access the machine to perform the "Winrm quickconfig" as the error message suggests.  Is it possible to gain true remote access on as a domain admin on domain machines using powershell v3?