Share via


Exercise 2: Remoting in PowerShell V2

Figure 1

PowerShell’s main purpose has always been to provide an easy way for IT professionals to manage servers, query information and, overall, automating a wide range of tasks on multiple software products from a single scripting solution.

However up until now, PowerShell V1 had a limited reach in terms of managing and accessing multiple computers at the same time. Because PowerShell is built on .Net, there has always been an option to create distributed scripts that would interact with each other. Pure remoting is way more than that.

PowerShell remoting means having the ability to invoke commands through the network on remote machines. If you are familiar with PowerShell you know that it is object-oriented using .Net. Unlike any remote shell you have probably seen in the past, this means that you not only have the option to access the CLI remotely (Telnet style), but you can also pull remote objects, have local references for them, and make transparent calls of their properties and methods through the network, just as if they were local objects.

Microsoft .Net’s remoting technologies are now being exploited in PowerShell. This makes it possible to invoke instances of objects whose types are not known by the local machine. In these cases all referenced calls are sent to the remote machine, the remote machine processes it, and sends back a serialized version of the resulting object when necessary. PowerShell’s remoting capabilities are built on Windows Remote Management (WinRM). In this exercise you will see how PowerShellV2 is combined with WinRM to easily create PowerShell Sessions that you can invoke and connect to.

Part 1: Invoking Remote Commands

Figure 2

Note:
The following exercise must be carried out on your server machine.

  1. Open an elevated PowerShell v2 prompt by accessing:

    Start All Programs Accessories Windows PowerShell

    and right clicking on Windows PowerShell and selecting R un as Administrator:

    Figure 3

  2. Click Yes when prompted by UAC.
  3. Since this is not a domain-based machine, we must make some changes in the registry by entering the following command:

    PowerShell

    new-itemproperty -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -name LocalAccountTokenFilterPolicy -propertyType DWord -value 1
  4. Next, we need to add the local machine to the list of trusted computers. To simplify things, we will add all machines by entering the following command (please note that we are adding all machines for the sake of simplicity, we do not recommend doing this at the enterprise level):

    PowerShell

    set-item wsman:localhost\client\trustedhosts -value *
  5. When all the requirements for remoting have been fulfilled, PowerShell V2 provides a very simple way to enable it, simply run the following command:

    PowerShell

    Enable-PSRemoting -force
    Note:
    For more information about the requirements for remoting in PowerShell V2 run the cmdlet “Get-Help About_Remote”
  6. Let’s first create a process to play with during this exercise. Run the following commands:

    PowerShell

    Start-Process Notepad
    Note:
    Notepad will open
  7. Return to the PowerShell window and type:

    PowerShell

    $notepadLocal = Get-Process Notepad
  8. We will connect to the localhost machine as if it were a remote machine. Use the following command to create a remote session (connection) to the machine:

    PowerShell

    New-PSSession –Computer localhost $remoteSession = Get-PSSession
    Note:
    If you have a domain and you want to set up a couple of machines of in that domain with PowerShell V2 (equal versions) and remoting, you can try this same procedure on different machines.
  9. Get a reference to the same Notepad process, except this time, do it remotely. To do this you need to invoke the Get-Process command remotely and assign the result to a variable.

    PowerShell

    $notepadRemote = Invoke-Command –Session $remoteSession –ScriptBlock { Get-Process Notepad }
    Note:
    You might expect at this point that $notepadLocal and $notepadRemote are the same, but they’re not. Through remoting you could get any kind of object, even if they’re not available locally. Instances are serialized and shipped.
  10. For comparison purposes query the methods in the $notepadLocal instance:

    PowerShell

    $notepadLocal | Get-Member –MemberType Method
    Note:
    You should see a list similar to the one below. Notice that the TypeName is System.Diagnostics.Process:

    Figure 4

  11. Try the same listing for the remote representation of the process:

    PowerShell

    $notepadRemote | Get-Member –MemberType Method
    Note:
    Now the result is very different, and even the TypeName is different after deserialization:

    Figure 5

    Note:
    Certain properties and methods in some remote objects have been excluded from remoting in PowerShell. This is a safety measure. However for some objects you will be able to invoke a method, and in those cases the execution will also be seamlessly remote.
  12. So, you cannot call any of the methods that were there originally. If we want to kill the Notepad process remotely, we might have to invoke the Kill method directly, and not indirectly.

    PowerShell

    Invoke-Command –Session $remoteSession –ScriptBlock { (Get-Process Notepad).Kill() }
    Note:
    Did that close the Notepad window remotely?
  13. Now try something slightly different, and start Notepad remotely:

    PowerShell

    Invoke-Command –Session $remoteSession –ScriptBlock { Start-Process Notepad }
  14. You should not be able to see Notepad open because it will open on a different session that you are using. However you should see that the process is running locally. Run the following command:

    PowerShell

    Get-Process Notepad

    Figure 6

  15. Before moving on, kill the Notepad process:

    PowerShell

    $notepadLocal = Get-Process Notepad $notepadLocal.Kill()

Part 2: Connecting to a Remote Session

Figure 7

Note:
In the previous part of this exercise you learned how to run script blocks remotely on a remote session. In that case, objects are serialized and shared through different sessions. However there is another option, you can connect to a remote session and use it just as if you were sitting in front of that computer.
  1. As a confirmation that we will be using separate sessions, run the following two commands:

    PowerShell

    $mySessionVar = 1 Start-Process Notepad
  2. To connect to our remote session simply run the following command:

    PowerShell

    Enter-PSSession $remoteSession
  3. Check $mySessionVar in this remote session by typing:

    PowerShell

    $mySessionVar

    Figure 8

    Note:
    The variable was not defined in this session and its value is therefore null.
  4. In the local session you started a process that is running Notepad. Because both sessions are running locally you should still be able to query the process in this remote session. Try to get the list of methods supported for the process in this remote session:

    PowerShell

    $notepadRemote = Get-Process Notepad $notepadRemote | Get-Member –MemberType Method
    Note:
    You are connected to a remote session and yet when you get the methods in the process you don’t see a serialized instance, you see the process as if you were looking at it locally:

    Figure 9

    Note:
    Basically you are not accessing the instances in your original session, that’s why they don’t need to be serialized. In this remoting mode you simply get a view of the remote session, there is no other form of interaction between the sessions.
  5. Kill the Notepad process that’s open in the original session and open a new one from the remote session:

    PowerShell

    $notepadRemote.Kill() Start-Process Notepad
    Note:
    You may notice that you cannot see the new Notepad window. This is happening because even though it looks as if you are using a local session, it is still a remote session.
  6. Exit the remote session to go back to the original.

    PowerShell

    Exit-PSSession
  7. Now, you should be back in the local session where you created $mySessionVar. Check its value to confirm this.

    Figure 10

  8. You started a Notepad process in the remote session. Verify that the process is running with the following command:

    PowerShell

    Get-Process Notepad
  9. You should see that the process is still there. The process was started in the remote session. You can close the remote session with the command:

    PowerShell

    Remove-PSSession $remoteSession
    Note:
    Is the Notepad process still running?

    Note:
    Please wait for the Instructor to resume the lecture.

Exercise-2: Conclusions

Figure 11

PowerShell is a strong automation framework that’s very easy to use for the IT Pro in Windows operating systems. All Microsoft product teams as well as several Partners are building on top of PowerShell making it possible to use it a common ground for the management of an entire Data Center infrastructure.

This growth has gaps that have been obvious almost from the beginning of PowerShell V1, and remoting is perhaps the most acclaimed feature by the PowerShell Community and users in general. Having the ability to send commands remotely in a simple, secure, agile manner is something that every PowerShell script writer has wanted at some point (or many). In this exercise you saw how you can make remote calls, and obtain serialized objects that give the apparent experience of using the remote instances as if they were local.

How many times have you wanted to open a PowerShell command prompt on two or three servers just to run a couple of commands and go? You saw how you can easily enter PS Sessions remotely and run commands just as if you were sitting in front the remote machine. PowerShell leverages to the advantages of WinRM and makes remoting available for you in Windows Vista and Windows Server 2008.