Evaluate Weigh the pros and cons of technologies, products and projects you are considering.

How to enable PowerShell remoting

You've heard how PowerShell remoting is changing in v3 of the product; now, learn how to use it -- and avoid traps.

Remoting was the most eagerly awaited feature in PowerShell v2. As a result, PowerShell's capabilities reached...

new heights. The following excerpt, provided by Manning Publications, describes enabling remoting. It is based on chapter 10 of PowerShell in Depth, by Don Jones, Richard Siddaway and Jeffery Hicks. See how remoting is improved in v3.

Want the whole thing? Manning Publications is offering a 40% discount on PowerShell in Depth to TechTarget readers. Use the promotional code 12pidtt at manning.com; if you buy the print book, the e-book is free.

Remoting needs to be enabled on any machine that will receive connections, which can include computers running either the Server or a client version of the Windows operating system. The easy way to set up remoting is to simply run Enable-PSRemoting. This command performs several tasks:

  • Start (or restart, if it’s already started) the WinRM service.
  • Set the WinRM service to start automatically from now on.
  • Create a WinRM listener for HTTP traffic on port 5985 for all local IP addresses.
  • Create a Windows Firewall exception for the WinRM listener. Note that this will fail on client versions of Windows if any network cards are configured to have a type of “Public,” because the firewall will refuse to create new exceptions on those cards. If this happens, change the network card’s type to something else (like “Work” or “Private,” as appropriate), and run Enable-PSRemoting again. Alternately, if you know you have some Public network cards, add the –SkipNetworkProfileCheck parameter to Enable-PSRemoting. Doing so will successfully create a firewall exception that allows incoming Remoting traffic only from the computer’s local subnet.

The command will also set up one or more of these four endpoints:

  • PowerShell 32-bit
  • PowerShell 64-bit
  • PowerShell Server Manager Workflow
  • PowerShell Workflow

Table 1 illustrates some example end point configurations. On a 32-bit machine, the endpoint is referred to as PowerShell rather than PowerShell32.

Table 1: Example endpoint configurations

PowerShell Version
32 bit
PowerShell 64bit
Server manager
Windows Server 2008 R2






Windows 7 64 bit






Windows 8 32 bit client






Windows 8 Server






Windows 7 client 32 bit standalone






You’ll be prompted several times as the command runs; be sure to reply “Y” for “Yes” so that each step can complete properly.

One-to-one remoting

The most straightforward way to use remoting is called one-to-one remoting, in which you essentially bring up an interactive PowerShell prompt on a remote computer. It’s pretty simple once remoting is enabled on the remote machine:

PS C:\> enter-pssession -ComputerName Win8

[Win8]: PS C:\Users\Administrator\Documents>

Note If you want to experiment with this, just use localhost as the computer name once you’ve enabled remoting on your computer. You’ll be “remotely controlling” your local machine but you’ll get the full remoting experience.

Notice how the PowerShell prompt changes to include the name of the computer you’re now connected to. From here, it’s almost exactly as if you were physically standing in front of that computer, and you can run any command that the remote machine contains. There are a few important caveats to keep in mind:

  1. By default, when the PowerShell prompt contains any computer name (even localhost), you cannot execute any other commands that initiate a Remoting connection. Doing so would create a “second hop,” which won’t work by default.
  2. You cannot run any commands that start a graphical application. If you do so, the shell may appear to freeze; hit Ctrl+C to end the process and regain control.
  3. You can’t run any command program that has its own “shell” like nslookup or netsh.
  4. You can only run scripts on the remote machine if its execution policy permits you to do so.
  5. You are not connected to an interactive desktop session; your connection will be audited as a “network logon,” much as if you were connecting to a file share on the remote machine. As a result of the connection type, Windows won’t execute profile scripts, although you will be connected to your profile home folder on the remote machine.
  6. Nothing you do will be visible by any other user who is connected to the same machine, even if they’re interactively logged on to its desktop console. In other words, you can’t run some application and have it “pop up” in front of the logged-on user.
  7. You must specify the computer’s name as it appears in Active Directory or in your local Trusted Hosts list; you can’t use IP addresses or DNS CNAME aliases unless those have been added to your Trusted Hosts list.

When you’re done with the remote machine, run Exit-PSSession. This will return you to your local prompt, close the connection to the remote machine, and free up resources on the remote machine. This will also happen automatically if you just close the PowerShell window.

[Win8]: PS C:\Users\Administrator\Documents> Exit-PSSession

PS C:\>

The way we’ve used Enter-PSSession will always connect to the remote machine’s default PowerShell endpoint. On a 64-bit operating system, that’ll be the 64-bit version of PowerShell. Later, we’ll show you how to connect to other endpoints (remembering that Enable-PSRemoting can create up to four endpoints in total).

One-to-many remoting

This is a powerful technique that really highlights the value of remoting. You’ll basically be transmitting a command (or a series of commands) to multiple remote computers. They’ll each execute the command, serialize the results into XML, and send the results back to you. Your copy of PowerShell will deserialize the XML into objects, and put them in the pipeline. For example, suppose we wanted to get a list of all processes whose names start with the letter “s,” from two different computers:

PS C:\> invoke-command -ScriptBlock { Get-Process -name s* } -computername


Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessN PSCompu

                                                          ame      terName

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

    217      11     3200       7080    33     1.23    496 services win8

     50       3      304        980     5     0.13    248 smss     win8

    315      16     2880       8372    46     0.03     12 spoolsv  win8

    472      36     8908      11540    60     0.31    348 svchost  win8

    306      12     2088       7428    36     0.19    600 svchost  win8

    295      15     2372       5384    29     0.61    636 svchost  win8

    380      15    17368      19428    55     0.56    728 svchost  win8

   1080      41    12740      25456   120     2.19    764 svchost  win8

    347      19     3892       8812    93     0.03    788 svchost  win8

    614      52    13820      18220  1129     2.28    924 svchost  win8

     45       4      508       2320    13     0.02   1248 svchost  win8

    211      18     9228       8408  1118     0.05   1296 svchost  win8

     71       6      804       3540    28     0.00   1728 svchost  win8

   2090       0      120        292     3    10.59      4 System   win8

    217      11     3200       7080    33     1.23    496 services loca...

     50       3      304        980     5     0.13    248 smss     loca...

    315      16     2880       8372    46     0.03     12 spoolsv  loca...

    469      36     8856      11524    59     0.31    348 svchost  loca...

    306      12     2088       7428    36     0.19    600 svchost  loca...

    295      15     2372       5384    29     0.61    636 svchost  loca...

    380      15    17368      19428    55     0.56    728 svchost  loca...

   1080      41    12740      25456   120     2.19    764 svchost  loca...

    347      19     3892       8812    93     0.03    788 svchost  loca...

    607      49    13756      18132  1129     2.28    924 svchost  loca...

     45       4      508       2320    13     0.02   1248 svchost  loca...

    211      18     9228       8408  1118     0.05   1296 svchost  loca...

     71       6      804       3540    28     0.00   1728 svchost  loca...

   2089       0      120        292     3    10.59      4 System   loca...

The command is Invoke-Command. Its –ScriptBlock parameter accepts the commands (use semicolons to separate multiple commands) you want transmitted to the remote machines; the –ComputerName parameter specifies the machine names. Alternatively, for longer commands a script block object could be created:

$sb = {Get-Process -Name s*}

Invoke-Command -ComputerName localhost,win8 -ScriptBlock $sb

As with Enter-PSSession, you must specify the computer’s name as it appears in Active Directory or in your local Trusted Hosts list; you can’t use IP addresses or DNS CNAME aliases unless those have been added to your Trusted Hosts list.

Notice anything interesting about the output? It contains an extra column named PSComputerName, which contains the name of the computer each result row came from. This is a handy way to separate, sort, group, and otherwise organize your results. This property is always added to the incoming results by PowerShell; if you’d rather not see the property in the output, add the –HideComputerName parameter to Invoke-Command. The property will still exist (and can be used for sorting and so forth), but it won’t be displayed in the output by default.

As with Enter-PSSession, Invoke-Command will use the default PowerShell endpoint on the remote machine, which in the case of a 64-bit OS will be the 64-bit shell.

By default, Invoke-Command will only talk to 32 computers at once. Doing so requires it to maintain a PowerShell instance in memory for each remote machine it’s talking to; 32 is a number Microsoft came up with that seems to work well in a variety of situations. If you specify more than 32 computers, the extra ones will just queue up, and Invoke-Command will start working with them as the first 32 begin to complete. You can change the level of parallelism by using the command’s –ThrottleLimit parameter, keeping in mind that higher numbers place a greater load on your computer, but no extra load on the remote machines.

Remoting caveats

The data sent from a remote machine to your computer has to be packaged in a way that makes it easy to transmit over the network. Serialization and deserialization, which we’ve already mentioned, makes it possible—but with some loss of functionality. For example, consider the type of object produced by Get-Service:

PS C:\> get-service | get-member

   TypeName: System.ServiceProcess.ServiceController

Name                      MemberType    Definition

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

Name                      AliasProperty Name = ServiceName

RequiredServices          AliasProperty RequiredServices = ServicesDepe...

Disposed                  Event         System.EventHandler Disposed(Sy...

Close                     Method        System.Void Close()

Continue                  Method        System.Void Continue()

CreateObjRef              Method        System.Runtime.Remoting.ObjRef ...

Dispose                   Method        System.Void Dispose()

Equals                    Method        bool Equals(System.Object obj)

ExecuteCommand            Method        System.Void ExecuteCommand(int ...

GetHashCode               Method        int GetHashCode()

GetLifetimeService        Method        System.Object GetLifetimeService()

GetType                   Method        type GetType()

InitializeLifetimeService Method        System.Object InitializeLifetim...

Pause                     Method        System.Void Pause()

Refresh                   Method        System.Void Refresh()

Start                     Method        System.Void Start(), System.Voi...

Stop                      Method        System.Void Stop()

WaitForStatus             Method        System.Void WaitForStatus(Syste...

CanPauseAndContinue       Property      bool CanPauseAndContinue {get;}

CanShutdown               Property      bool CanShutdown {get;}

CanStop                   Property      bool CanStop {get;}

Container                 Property      System.ComponentModel.IContaine...

DependentServices         Property      System.ServiceProcess.ServiceCo...

DisplayName               Property      string DisplayName {get;set;}

MachineName               Property      string MachineName {get;set;}

ServiceHandle             Property      System.Runtime.InteropServices....

ServiceName               Property      string ServiceName {get;set;}

ServicesDependedOn        Property      System.ServiceProcess.ServiceCo...

ServiceType               Property      System.ServiceProcess.ServiceTy...

Site                      Property      System.ComponentModel.ISite Sit...

Status                    Property      System.ServiceProcess.ServiceCo...

ToString                  ScriptMethod  System.Object ToString();

As you can see, these objects’ members include several properties, which let you stop the service, pause it, and so on. Now. consider that exact same kind of object retrieved, via remoting, from a remote machine:

PS C:\> invoke-command -ComputerName win8 -ScriptBlock { Get-Service } |

>> Get-Member


   TypeName: Deserialized.System.ServiceProcess.ServiceController


Name                MemberType   Definition

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

ToString            Method       string ToString(), string ToString(str...

Name                NoteProperty System.String Name=AeLookupSvc

PSComputerName      NoteProperty System.String PSComputerName=win8

PSShowComputerName  NoteProperty System.Boolean PSShowComputerName=True

RequiredServices    NoteProperty Deserialized.System.ServiceProcess.Ser...

RunspaceId          NoteProperty System.Guid RunspaceId=00e784f7-6c27-4...

CanPauseAndContinue Property     System.Boolean {get;set;}

CanShutdown         Property     System.Boolean {get;set;}

CanStop             Property     System.Boolean {get;set;}

Container           Property      {get;set;}

DependentServices   Property     Deserialized.System.ServiceProcess.Ser...

DisplayName         Property     System.String {get;set;}

MachineName         Property     System.String {get;set;}

ServiceHandle       Property     System.String {get;set;}

ServiceName         Property     System.String {get;set;}

ServicesDependedOn  Property     Deserialized.System.ServiceProcess.Ser...

ServiceType         Property     System.String {get;set;}

Site                Property      {get;set;}

Status              Property     System.String {get;set;}

The methods (excepting the universal ToString() method) are gone. That’s because you’re looking at a deserialized version of the object (it says so right in the TypeName at the top of the output), and the methods are stripped off. Essentially, you’re getting a read-only, static version of the object.

This isn’t necessarily a downside, as serialization and the removal of methods don’t occur until the remote commands finish executing and their output is being packaged for transmission. The objects are still “live” objects when they’re on the remote computer, so you simply have to start them, stop them, pause them, or whatever on the remote machine. In other words, any “actions” you need to take need to be part of the command you send to the remote machine for execution.

Dig Deeper on Microsoft Windows Server 2012