Using Windows PowerShell Remoting
- 7/15/2013
- Using Windows PowerShell remoting
- Configuring Windows PowerShell remoting
- Troubleshooting Windows PowerShell remoting
- Summary
Configuring Windows PowerShell remoting
Windows Server 2012 installs with Windows Remote Management (WinRm) configured and running to support remote Windows PowerShell commands. WinRm is the Microsoft implementation of the industry standard WS-Management Protocol. As such, WinRM provides a firewall-friendly method of accessing remote systems in an interoperable manner. It is the remoting mechanism used by the new Common Information Model (CIM) cmdlets (the CIM cmdlets are covered in Chapter 9, “Using CIM”). As soon as Windows Server 2012 is up and running, you can make a remote connection and run commands or open an interactive Windows PowerShell console. A Windows 8 client, on the other hand, ships with WinRm locked down. Therefore, the first step is to use the Enable-PSRemoting function to configure remoting. When running the Enable-PSRemoting function, the following steps occur:
- Starts or restarts the WinRM service.
- Sets the WInRM service startup type to Automatic.
- Creates a listener to accept requests from any Internet Protocol (IP) address.
- Enables inbound firewall exceptions for WS_Management traffic.
- Sets a target listener named Microsoft.powershell.
- Sets a target listener named Microsoft.powershell.workflow.
- Sets a target listener named Microsoft.powershell32.
During each step of this process, the function prompts you to agree or not agree to performing the specified action. If you are familiar with the steps the function performs, and you do not make any changes from the defaults, you can run the command with the Force switched parameter and it will not prompt prior to making the changes. The following example shows the syntax of this command:
Enable-PSRemoting -Force
The following example shows the use of the Enable-PSRemoting function in interactive mode, along with all associated output from the command:
PS C:\> Enable-PSRemoting WinRM Quick Configuration Running command "Set-WSManQuickConfig" to enable remote management of this computer by using the Windows Remote Management (WinRM) service. This includes: 1. Starting or restarting (if already started) the WinRM service 2. Setting the WinRM service startup type to Automatic 3. Creating a listener to accept requests on any IP address 4. Enabling Windows Firewall inbound rule exceptions for WS-Management traffic (for http only). Do you want to continue? [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):y WinRM has been updated to receive requests. WinRM service type changed successfully. WinRM service started. WinRM has been updated for remote management. Created a WinRM listener on HTTP://* to accept WS-Man requests to any IP on this mac hine. WinRM firewall exception enabled. Confirm Are you sure you want to perform this action? Performing operation "Set-PSSessionConfiguration" on Target "Name: microsoft.powershell SDDL: O:NSG:BAD:P(A;;GA;;;BA)(A;;GA;;;RM)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD). This will allow selected users to remotely run Windows PowerShell commands on this computer". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):y Confirm Are you sure you want to perform this action? Performing operation "Set-PSSessionConfiguration" on Target "Name: microsoft.powershell.workflow SDDL: O:NSG:BAD:P(A;;GA;;;BA)(A;;GA;;;RM)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD). This will allow selected users to remotely run Windows PowerShell commands on this computer". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):y Confirm Are you sure you want to perform this action? Performing operation "Set-PSSessionConfiguration" on Target "Name: microsoft.powershell32 SDDL: O:NSG:BAD:P(A;;GA;;;BA)(A;;GA;;;RM)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD). This will allow selected users to remotely run Windows PowerShell commands on this computer". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):y PS C:\>
Once configured, use the Test-WSMan cmdlet to ensure the WinRM remoting is properly configured and is accepting requests. A properly configured system replies with the following data:
PS C:\> Test-WSMan -ComputerName w8c504 wsmid : httP://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd ProtocolVersion : httP://schemas.dmtf.org/wbem/wsman/1/wsman.xsd ProductVendor : Microsoft Corporation ProductVersion : OS: 0.0.0 SP: 0.0 Stack: 3.0
This cmdlet works with Windows PowerShell 2.0 remoting as well. Keep in mind that configuring WinRM through the Enable-PSRemoting function does not enable the WinRM firewall exception, and therefore PING commands will not work by default when pinging to a Windows 8 client system.
Running commands
For simple configuration on a single remote machine, entering a remote Windows PowerShell session is the answer. To enter a remote Windows PowerShell session, use the Enter-PSSession cmdlet to create an interactive remote Windows PowerShell session on a target machine. If you do not supply credentials, the remote session impersonates your current logon. The output in the following example illustrates connecting to a remote computer named dc1:
PS C:\> Enter-PSSession -ComputerName dc1 [dc1]: PS C:\Users\Administrator\Documents> sl C:[dc1]: PS C:\> gwmi win32_bios SMBIOSBIOSVersion : A01 Manufacturer : Dell Computer Corporation Name : Default System BIOS SerialNumber : 9HQ1S21 Version : DELL - 6 [dc1]: PS C:\> exit PS C:\>
Once established, the Windows PowerShell prompt changes to include the name of the remote system. The Set-Location (sl is an alias) changes the working directory on the remote system to C:\. Next, the Get-WmiObject cmdlet retrieves the BIOS information on the remote system. The Exit command exits the remote session and the Windows PowerShell prompt returns to the default.
The good thing is that when using the Windows PowerShell transcript tool through Start-Transcript, the transcript tool captures output from the remote Windows PowerShell session as well as output from the local session. Indeed, all commands typed appear in the transcript. The following commands illustrate beginning a transcript, entering a remote Windows PowerShell session, typing a command, exiting the session, and stopping the transcript:
PS C:\> Start-Transcript Transcript started, output file is C:\Users\administrator.IAMMRED\Documents\PowerShe ll_transcript.20120701124414.txt PS C:\> Enter-PSSession -ComputerName dc1 [dc1]: PS C:\Users\Administrator\Documents> gwmi win32_bios SMBIOSBIOSVersion : A01 Manufacturer : Dell Computer Corporation Name : Default System BIOS SerialNumber : 9HQ1S21 Version : DELL - 6 [dc1]: PS C:\Users\Administrator\Documents> exit PS C:\> Stop-Transcript Transcript stopped, output file is C:\Users\administrator.IAMMRED\Documents\PowerShe ll_transcript.20120701124414.txt PS C:\>
Figure 7-1 shows the transcript from the preceding remote Windows PowerShell session. The transcript contains all commands, including the ones from the remote computer, and associated output.
Figure 7-1 The transcript tool works in remote Windows PowerShell sessions as well as in local Windows PowerShell console sessions.
Running a single Windows PowerShell command
When you have a single command to run, it does not make sense to go through all the trouble of building and entering an interactive, remote Windows PowerShell session. Instead of creating a remote Windows PowerShell console session, you can run a single command by using the Invoke-Command cmdlet. If you have a single command to run, use the cmdlet directly and specify the computer name as well as any credentials required for the connection. The following example shows this technique, with the last process running on the ex1 remote server:
PS C:\> Invoke-Command -ComputerName ex1 -ScriptBlock {gps | select -Last 1} Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName PSComputerName ------- ------ ----- ----- ----- ------ -- ----------- ------------ 224 34 47164 51080 532 0.58 10164 wsmprovhost ex1
When you work interactively in a Windows PowerShell console, you might not want to type a long command, even when using tab expansion to complete the command. To shorten the amount of typing, you can use the icm alias for the Invoke-Command cmdlet. You can also rely upon positional parameters (the first parameter is the computer name and the second parameter is the script block). By using aliases and positional parameters, the previous command shortens considerably, as shown in the following example:
PS C:\> icm ex1 {gps | select -l 1} Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName PSComputerName ------- ------ ----- ----- ----- ------ -- ----------- ------------ 221 34 47260 51048 536 0.33 4860 wsmprovhost ex1
Running a single command against multiple computers
Use of the Invoke-Command exposes one of the more powerful aspects of Windows PowerShell remoting, which is running the same command against a large number of remote systems. The secret behind this power is that the computername parameter from the Invoke-Command cmdlet accepts an array of computer names. In the output appearing here, an array of computer names is stored in the variable $cn. Next, the $cred variable holds the credential object for the remote connections. Finally, the Invoke-Command cmdlet is used to make connections to all the remote machines and to return the BIOS information from the systems. The nice thing about this technique is that an additional parameter, PSComputerName, is added to the returning object, permitting easy identification of which BIOS is associated with which computer system. The following example shows the commands and associated output:
PS C:\> $cn = "dc1","dc3","ex1","sql1","wsus1","wds1","hyperv1","hyperv2","hyperv3" PS C:\> $cred = Get-Credential iammred\administrator PS C:\> Invoke-Command -cn $cn -cred $cred -ScriptBlock {gwmi win32_bios} SMBIOSBIOSVersion : BAP6710H.86A.0072.2011.0927.1425 Manufacturer : Intel Corp. Name : BIOS Date: 09/27/11 14:25:42 Ver: 04.06.04 SerialNumber : Version : INTEL - 1072009 PSComputerName : hyperv3 SMBIOSBIOSVersion : A11 Manufacturer : Dell Inc. Name : Phoenix ROM BIOS PLUS Version 1.10 A11 SerialNumber : BDY91L1 Version : DELL - 15 PSComputerName : hyperv2 SMBIOSBIOSVersion : A01 Manufacturer : Dell Computer Corporation Name : Default System BIOS SerialNumber : 9HQ1S21 Version : DELL - 6 PSComputerName : dc1 SMBIOSBIOSVersion : 090004 Manufacturer : American Megatrends Inc. Name : BIOS Date: 03/19/09 22:51:32 Ver: 09.00.04 SerialNumber : 3692-0963-1044-7503-9631-2546-83 Version : VRTUAL - 3000919 PSComputerName : wsus1 SMBIOSBIOSVersion : V1.6 Manufacturer : American Megatrends Inc. Name : Default System BIOS SerialNumber : To Be Filled By O.E.M. Version : 7583MS - 20091228 PSComputerName : hyperv1 SMBIOSBIOSVersion : 080015 Manufacturer : American Megatrends Inc. Name : Default System BIOS SerialNumber : None Version : 091709 - 20090917 PSComputerName : sql1 SMBIOSBIOSVersion : 080015 Manufacturer : American Megatrends Inc. Name : Default System BIOS SerialNumber : None Version : 091709 - 20090917 PSComputerName : wds1 SMBIOSBIOSVersion : 090004 Manufacturer : American Megatrends Inc. Name : BIOS Date: 03/19/09 22:51:32 Ver: 09.00.04 SerialNumber : 8994-9999-0865-2542-2186-8044-69 Version : VRTUAL - 3000919 PSComputerName : dc3 SMBIOSBIOSVersion : 090004 Manufacturer : American Megatrends Inc. Name : BIOS Date: 03/19/09 22:51:32 Ver: 09.00.04 SerialNumber : 2301-9053-4386-9162-8072-5664-16 Version : VRTUAL - 3000919 PSComputerName : ex1 PS C:\>
Creating a persisted connection
If you anticipate making multiple connections to a remote system, use the New-PSSession cmdlet to create a remote Windows PowerShell session. The New-PSSession cmdlet permits you to store the remote session in a variable and provides you with the ability to enter and leave the remote session as often as required, without the additional overhead of creating and destroying remote sessions. In the commands that follow, a new Windows PowerShell session is created through the New-PSSession cmdlet. The newly created session is stored in the $dc1 variable. Next, the Enter-PSSession cmdlet is used to enter the remote session by using the stored session. A command retrieves the remote hostname, and the remote session is exited through the Exit command. Next, the session is re-entered and the last process retrieved. The session is exited once again. Finally, the Get-PSSession cmdlet retrieves Windows PowerShell sessions on the system, and all sessions are removed through the Remove-PSSession cmdlet:
PS C:\> $dc1 = New-PSSession -ComputerName dc1 -Credential iammred\administrator PS C:\> Enter-PSSession $dc1 [dc1]: PS C:\Users\Administrator\Documents> hostname dc1 [dc1]: PS C:\Users\Administrator\Documents> exit PS C:\> Enter-PSSession $dc1 [dc1]: PS C:\Users\Administrator\Documents> gps | select -Last 1 Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 292 9 39536 50412 158 1.97 2332 wsmprovhost [dc1]: PS C:\Users\Administrator\Documents> exit PS C:\> Get-PSSession Id Name ComputerName State ConfigurationName Availability -- ---- ------------ ----- ----------------- ------------ 8 Session8 dc1 Opened Microsoft.PowerShell Available PS C:\> Get-PSSession | Remove-PSSession PS C:\>
If you have several commands, or if you anticipate making multiple connections, the Invoke-Command cmdlet accepts a session parameter in the same manner as the Enter-PSSession cmdlet does. In the output appearing here, a new PSSession is created to a remote computer named dc1. The remote session is used to retrieve two different pieces of information. Once completed, the session stored in the $dc1 variable is explicitly removed:
PS C:\> $dc1 = New-PSSession -ComputerName dc1 -Credential iammred\administrator PS C:\> Invoke-Command -Session $dc1 -ScriptBlock {hostname} dc1 PS C:\> Invoke-Command -Session $dc1 -ScriptBlock {Get-EventLog application -Newest 1} Index Time EntryType Source InstanceID Message PSCompu terName ----- ---- --------- ------ ---------- ------- ------- 17702 Jul 01 12:59 Information ESENT 701 DFSR… dc1 PS C:\> Remove-PSSession $dc1
You can also create persisted connection to multiple computers. This enables you to use the Invoke-Command cmdlet to run multiple commands against multiple remote computers. The first thing is to create a new PSSession that contains multiple computers. You can do this by using alternative credentials. Create a variable that holds the credential object returned by the Get-Credential cmdlet. A dialog box appears, permitting you to enter the credentials. Figure 7-2 shows the dialog box.
Figure 7-2 Store remote credentials in a variable populated through the Get-Credential cmdlet.
Once you have stored the credentials in a variable, create another variable to store the remote computer names. Next, use the New-PSSession cmdlet to create a new Windows PowerShell session using the computer names stored in the computer name variable and the credentials stored in the credential variable. To be able to reuse the Windows PowerShell remote session, store the newly created Windows PowerShell session in a variable as well. The following example illustrates storing the credentials, computer names, and newly created Windows PowerShell session:
$cred = Get-Credential -Credential iammred\administrator $cn = "ex1","dc3" $ps = New-PSSession -ComputerName $cn -Credential $cred
Once the Windows PowerShell session is created and stored in a variable, it can be used to execute commands against the remote computers. To do this, use the Invoke-Command cmdlet, as shown in the following example:
PS C:\> Invoke-Command -Session $ps -ScriptBlock {gsv | select -First 1} Status Name DisplayName PSComputerName ------ ---- ----------- -------------- Stopped AeLookupSvc Application Experience ex1 Running ADWS Active Directory Web Services dc3
The great thing about storing the remote connection in a variable is that it can be used for additional commands as well. The following example shows the command that returns the first process from each of the two remote computers:
PS C:\> Invoke-Command -Session $ps -ScriptBlock {gps | select -First 1} Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName PSComputerName ------- ------ ----- ----- ----- ------ -- ----------- ------------ 47 7 1812 6980 53 0.70 3300 conhost dc3 32 4 824 2520 22 0.22 1140 conhost ex1
Figure 7-3 shows the commands to store the credentials, create a remote Windows Power Shell connection to two different computers, and run two remote commands against them. Figure 7-3 also shows the output associated with the commands.
Figure 7-3 By creating and by storing a remote Windows PowerShell connection, it becomes easy to run commands against multiple computers.