The previous article (link) in this series explored Active Directory Domain Services management with PowerShell. Now we will examine the remoting features in PowerShell 4.0 and explore the protocols, services, and configurations needed for remoting to function. There will be demonstrations to highlight how remoting works by getting information, creating objects, changing settings, and assigning user permissions to a group of computers remotely.

Windows PowerShell Remoting

Windows PowerShell remoting provides a method to transmit any command to a remote computer for local execution. The commands do not have to be available on the computer that originates the connection; it is enough if just the remote computers are able to execute the commands.

Windows PowerShell remoting relies on the web services managements (WS-Man) protocol. WS-Management is a distributed management task force (DMTF) open standard that depends on HTTP (or HTTPS) protocol. The Windows Remote Management (WinRM) service is the Microsoft implementation of WS-Management, WinRM is at the heart of Windows PowerShell remoting but this service can also be used by other non-PowerShell applications.

By default, WS-Man and PowerShell remoting uses port 5985 and 5986 for connections over HTTP and HTTPS, respectively. This is much friendlier to network firewalls when compared to other legacy communication protocols such as the distributed component object model (DCOM) and remote procedure call (RPC), which use numerous ports and dynamic port mappings.

Remoting is enabled by default on Windows Server 2012 and it is required by the server manager console to communicate with other Windows servers, and even to connect to the local computer where the console is running. On client operating systems, such as Windows 7 or Windows 8, remoting is not enabled by default.

Once enabled, remoting registers at least one listener. Each listener accepts incoming traffic through either HTTP or HTTPS; listeners can be bound to one or multiple IP addresses. Incoming traffic specifies the intended destination or endpoint. These endpoints are also known as session configurations.

When traffic is directed to an endpoint, WinRM starts the PowerShell engine, hands off the incoming traffic, and waits for PowerShell to complete its task. PowerShell will then pass the results to WinRM, and WinRM handles the transmission of that data back to the computer that originated the commands.

While this article concentrates on the remoting feature of Windows PowerShell, it is worth noting that there are other remote connectivity protocols that are also used by specific PowerShell cmdlets. For instance, some cmdlets use the RPC protocol, others depend on the remote registry service. These numerous communication protocols demand additional configuration on the firewall to allow those PowerShell commands to be executed across the network.

Enabling PowerShell Remoting on a Local Computer

You may need to enable remoting on Windows clients, older Windows Server operating systems, or Windows Server 2012 if it has been disabled. However, keep in mind that remoting must be enabled only on computers that you will connect to; no configuration is needed on the computer from which you are sending the commands.

To manually enable remoting, run the Enable-PSremoting cmdlet as shown below:

Running the Enable-PSremoting cmdlet makes the following changes to the computer:

  • * Sets the WinRM service to start automatically and restart it.
  • * Registers the default endpoints (session configurations) for use by Windows PowerShell.
  • * Creates an HTTP listener on port 5985 for all local IP addresses.
  • * Creates an exception in the Windows Firewall for incoming TCP traffic on port 5985.

If one or more network adapters in a computer are set to public (as an alternative to work or domain), you must use the –SkipNetworkProfileCheck parameter for the Enable-PSremoting cmdlet to succeed.

Running Get-PSSessionConfiguration exposes the endpoints created by Enable-PSremoting.

Enabling PowerShell Remoting Using Group Policy

If you have a large number of computers, configuring a group policy object (GPO) may be a better option to enable remoting than manually executing the Enable-PSremoting cmdlet in each system.

The order is not important, but the following three steps must be completed for the GPO to trickle down effectively and enable remoting on your domain computers:

  • * Create a Windows firewall exception for the WinRM service on TCP port 5985
  • * Allow the WinRM service to automatically listen for HTTP requests
  • * Set the WinRM Service to start automatically

Create a windows firewall exception for the WinRM service on TCP port 5985

  1. To create the firewall exception, use the Group Policy Management Console navigate to Computer Configuration\Administrative Templates\Network\Network Connections \Windows Firewall\Domain Profile.
  2. Right-click the Windows Firewall: Define inbound program exceptions and select Edit.
  3. Click on Show and on the Show Contents dialog box; under Value enter the following line: 5985:TCP:*:Enabled:WinRM as seen below:

    Allow the WinRM service to automatically listen for HTTP requests

    1. Again using Group Policy Management, that setting can be located under Computer Configuration\Administrative Templates\Windows Components\Windows Remote Management (WinRM)\WinRM Service.
    2. Right-click Allow remote server management through WinRM and select Edit. Click on Enabled and specify the IPv4 and IPv6 filters, which define which IP addresses listeners will be configured on. You can enter the * wildcard to indicate all IP addresses.

    Set the WinRM Service to start automatically

    1. This setting can be found on Computer Configuration\Windows Settings\Security Settings\System Services\Windows Remote management (WS-Management).
    2. Right-click Windows Remote management (WS-Management), select Properties and set the startup mode to “Automatic.”

    Once all the preceding GPO settings are completed and the group policy is applied, your domain computers within the policy scope will be ready to accept incoming PowerShell remoting connections.

Using Remoting

There are two common options for approaching remoting with PowerShell. The first is known as one-to-one remoting, in which you make a single remote connection and a prompt is displayed on the screen, where you can enter the commands that are executed on the remote computer. On the surface, this connection looks like an SSH or telnet session, even though it is a very different technology under the hood. The second option is called one-to-many remoting and it is especially suited for situations when you may want to run the same commands or scripts in parallel to several remote computers.

One-to-One Remoting (1:1)

The Enter-PSSession cmdlet is used to start a one-to-one remoting session. After you execute the command, the Windows PowerShell prompt changes to indicate the name of the computer that you are connected to. See figure below.

During this one-to-one session, the commands you enter on the session prompt are transported to the remote computer for execution. The commands’ output is serialized into XML format and transmitted back to your computer, which then deserializes the XML data into objects and carries them into the Windows PowerShell pipeline. At the session prompt, you are not limited to just entering commands, you can run scripts, import PowerShell modules, or add PSSnapins that are registered to the remote computer.

There are some caveats on this remoting feature that you need to be aware of. By default, WinRM only allows remote connections to the actual computer name; IP addresses or DNS aliases will fail. PowerShell does not load profile scripts on the remote computer; to run other PowerShell scripts; the execution policy on the remote computer must be set to allow it. If you use the Enter-PSSession cmdlet in a script, the script would run on the local machine to make the connection, but none of the script commands would be executed remotely because they were not entered interactively in the session prompt,

One-to-Many Remoting

With one-to-many remoting, you can send a single command or script to multiple computers at the same time. The commands are transported and executed on the remote computers, and each computer serializes the results into XML format before sending them back to your computer. Your computer deserializes the XML output into objects and moves them to the pipeline in the current PowerShell session.

The Invoke-Command cmdlet is used to execute one-to-many remoting connections. The -ComputerName parameter of the Invoke-Command accepts an array of names (strings); it can also receive the names from a file or get them from another source. For instance:

  • A comma-separated list of computers:
    • -ComputerName FS1,CoreG2,Server1
  • Reads names from a text file named servers.txt:
    • -ComputerName (Get-Content C:\Servers.txt)
  • Reads a CSV file named Comp.csv that has a computer column with computer names.
    • -ComputerName (Import-CSV C:\Comp.csv | Select –Expand Computer)
  • Queries Active Directory for computer objects
    • -ComputerName (Get-ADComputer –filter * | Select –Expand Name)

Here is an example of using remoting to obtain the MAC addresses of a group of computers:

 Invoke-Command -ComputerName FS1,CoreG2,Server1 -ScriptBlock `
{Get-NetAdapter |Select-Object -Property SystemName,Name,MacAddress |

Here is the output:

Here is another example: Let’s say that you need to create a folder on each computer to store drivers and, at the same time, you want to assign full control permission to a domain user, named User1, to access the folder. Here is one way you could code the solution:

Invoke-Command -ComputerName Fs1,CoreG2,Server1,Win81A `
-ScriptBlock {New-Item -ItemType Directory -Path c:\Drivers
$acl = Get-Acl c:\Drivers 
$User1P = "lanztek\User1","FullControl","Allow"
$user1A =New-Object System.Security.AccessControl.FileSystemAccessRule $User1P
$acl | set-acl c:\Drivers} 

The preceding script may be run from any accessible computer in the network. It creates a folder named “Drivers” on the root of the C drive on each one of the computers that it touches. The $acl variable stores the security descriptor of the Drivers folders; $User1P defines the permission level for User1 (full control). The $User1A variable holds a new object that defines an access rule for a file or directory. $User1A is used to modify the security descriptor ($acl). The last line of the script pipes the modified security descriptor ($acl) to the Set-Acl cmdlet. Finally, the Set-Acl cmdlet applies the security descriptor to the Drivers folder.

Once the scripts executes, you get immediate confirmation that the folder has been created on each one of the remote computers.

One-to-many remoting can be used again to verify that User1 has full control permission to the Drivers folder:

Invoke-Command -ComputerName Fs1,CoreG2,Server1,Win81A `
-ScriptBlock {get-acl c:\drivers | 
Select-Object PSComputername,AccessToString} 

By default, remoting connects up to 32 computers at the same time. If you include more than 32 computers, PowerShell starts working with the first 32 and queues the remaining ones. As computers from the first batch complete their tasks, the others are pulled from the queue for processing. It is possible to use the Invoke-Command cmdlet with the -ThrottleLimit parameter to increase or decrease that number.

Persistent PSSessions

When using Invoke-Command with the –ComputerName parameter, the remote computer creates a new instance of PowerShell to run your commands or scripts, sends the results back to you, and then closes the session. Each time Invoke-Command runs, even if it does to the same computers, a new session is created and any work done by a previous session will not be available in memory to the new connection. The same can be said when you use the Enter-PSSession with the –ComputerName parameter and then exit the connection by closing the console or using the Exit-PSSession command.

It is good to know that PowerShell has the capability to establish persistent connections (PSSessions) by using the New-PSSession cmdlet. The New-PSSession allows you to launch a connection to one or more remote computers and starts an instance of Windows PowerShell on every target computer. Then you run Enter-PSSession or Invoke Command with their –Session parameter to use the existing PSSession instead of starting a new session. Now you can execute commands on the remote computer and exit the session without killing the connection. Superb!

In the following example, the New-PSSession cmdlet is used to create four different PSSessions; the PSSessions are stored in a variable names $Servers. Get-Content reads the computer names from a text file named Servers.txt and pass that information to New-PSSession via the -ComputerName parameter.

$Servers = New-PSSession -ComputerName (Get-Content c:\Servers.txt) 

After running the command, typing $Servers or Get-PSSession will allow you to confirm that the sessions have been created.

Closing Remarks

Remoting is a firewall-friendly feature that relies on the WS-Management (WS-Man) open standard protocol to function. Microsoft implements and manage WS-Man via the WinRM service. This article shows how to administer from a small to a large number of computers with Windows PowerShell remoting using interactive sessions, one-to-one, one-to-many, and persistent PSSessions. But wait, there’s more. We have not talked yet about multihop remoting, implicit remoting, managing non-domain computers, or PowerShell web access. Those and other topics will be explained and demonstrated in our next article in this series.