Using PowerShell Remoting and Jobs
- 2/15/2013
- Understanding Windows PowerShell remoting
- Using Windows PowerShell jobs
- Using Windows PowerShell remoting: step-by-step exercises
- Chapter 4 quick reference
After completing this chapter, you will be able to:
Use Windows PowerShell remoting to connect to a remote system.
Use Windows PowerShell remoting to run commands on a remote system.
Use Windows PowerShell jobs to run commands in the background.
Receive the results of background jobs.
Keep the results from background jobs.
Understanding Windows PowerShell remoting
One of the great improvements in Microsoft Windows PowerShell 3.0 is the change surrounding remoting. The configuration is easier than it was in Windows PowerShell 2.0, and in most cases, Windows PowerShell remoting just works. When talking about Windows PowerShell remoting, a bit of confusion can arise because there are several different ways of running commands against remote servers. Depending on your particular network configuration and security needs, one or more methods of remoting may not be appropriate.
Classic remoting
Classic remoting in Windows PowerShell relies on protocols such as DCOM and RPC to make connections to remote machines. Traditionally, these protocols require opening many ports in the firewall and starting various services that the different cmdlets utilize. To find the Windows PowerShell cmdlets that natively support remoting, use the Get-Help cmdlet. Specify a value of computername for the -parameter parameter of the Get-Help cmdlet. This command produces a nice list of all cmdlets that have native support for remoting. The command and associated output appear here:
PS C:\> get-help * -Parameter computername | sort name | ft name, synopsis -auto -wrap Name Synopsis ---- -------- Add-Computer Add the local computer to a domain or workgroup. Add-Printer Adds a printer to the specified computer. Add-PrinterDriver Installs a printer driver on the specified computer. Add-PrinterPort Installs a printer port on the specified computer. Clear-EventLog Deletes all entries from specified event logs on the local or remote computers. Connect-PSSession Reconnects to disconnected sessions. Connect-WSMan Connects to the WinRM service on a remote computer. Disconnect-PSSession Disconnects from a session. Disconnect-WSMan Disconnects the client from the WinRM service on a remote computer. Enter-PSSession Starts an interactive session with a remote computer. Get-CimAssociatedInstance Get-CimAssociatedInstance [-InputObject] <ciminstance> [[-Association] <string>] [-ResultClassName <string>] [-Namespace <string>] [-OperationTimeoutSec <uint32>] [-ResourceUri <uri>] [-ComputerName <string[]>] [-KeyOnly] [<CommonParameters>] Get-CimAssociatedInstance [-InputObject] <ciminstance> [[-Association] <string>] -CimSession <CimSession[]> [-ResultClassName <string>] [-Namespace <string>] [-OperationTimeoutSec <uint32>] [-ResourceUri <uri>] [-KeyOnly] [<CommonParameters>] Get-CimClass Get-CimClass [[-ClassName] <string>] [[-Namespace] <string>] [-OperationTimeoutSec <uint32>] [-ComputerName <string[]>] [-MethodName <string>] [-PropertyName <string>] [-QualifierName <string>] [<CommonParameters>] Get-CimClass [[-ClassName] <string>] [[-Namespace] <string>] -CimSession <CimSession[]> [-OperationTimeoutSec <uint32>] [-MethodName <string>] [-PropertyName <string>] [-QualifierName <string>] [<CommonParameters>] Write-EventLog Writes an event to an event log.
As you can see, many of the Windows PowerShell cmdlets that have the -computername parameter relate to Web Services Management (WSMAN), Common Information Model (CIM), or sessions. To remove these cmdlets from the list, modify the command a bit to use Where-Object (? Is an alias for Where-Object). The revised command and associated output appear here:
PS C:\> Get-Help * -Parameter computername -Category cmdlet | ? modulename -match 'PowerShell.Management' | sort name | ft name, synopsis -AutoSize -Wrap Name Synopsis ---- -------- Add-Computer Add the local computer to a domain or workgroup. Clear-EventLog Deletes all entries from specified event logs on the local or remote computers. Get-EventLog Gets the events in an event log, or a list of the event logs, on the local or remote computers. Get-HotFix Gets the hotfixes that have been applied to the local and remote computers. Get-Process Gets the processes that are running on the local computer or a remote computer. Get-Service Gets the services on a local or remote computer. Get-WmiObject Gets instances of Windows Management Instrumentation (WMI) classes or information about the available classes. Invoke-WmiMethod Calls Windows Management Instrumentation (WMI) methods. Limit-EventLog Sets the event log properties that limit the size of the event log and the age of its entries. New-EventLog Creates a new event log and a new event source on a local or remote computer. Register-WmiEvent Subscribes to a Windows Management Instrumentation (WMI) event. Remove-Computer Removes the local computer from its domain. Remove-EventLog Deletes an event log or unregisters an event source. Remove-WmiObject Deletes an instance of an existing Windows Management Instrumentation (WMI) class. Rename-Computer Renames a computer. Restart-Computer Restarts ("reboots") the operating system on local and remote computers. Set-Service Starts, stops, and suspends a service, and changes its properties. Set-WmiInstance Creates or updates an instance of an existing Windows Management Instrumentation (WMI) class. Show-EventLog Displays the event logs of the local or a remote computer in Event Viewer. Stop-Computer Stops (shuts down) local and remote computers. Test-Connection Sends ICMP echo request packets ("pings") to one or more computers.
<-- output truncated -->
Some of the cmdlets provide the ability to specify credentials. This allows you to use a different user account to make the connection and to retrieve the data. Figure 4-1 displays the credential dialog box that appears when the cmdlet runs.
Figure 4-1 Cmdlets that support the -credential parameter prompt for credentials when supplied with a user name.
This technique of using the -computername and -credential parameters in a cmdlet appears here:
PS C:\> Get-WinEvent -LogName application -MaxEvents 1 -ComputerName ex1 -Credential nwtraders\administrator TimeCreated ProviderName Id Message ----------- ------------ -- ------- 7/1/2012 11:54:14 AM MSExchange ADAccess 2080 Process MAD.EXE (...
However, as mentioned earlier, use of these cmdlets often requires opening holes in the firewall or starting specific services. By default, these types of cmdlets fail when run against remote machines that don’t have relaxed access rules. An example of this type of error appears here:
PS C:\> Get-WinEvent -LogName application -MaxEvents 1 -ComputerName dc1 -Credential nwtraders\administrator Get-WinEvent : The RPC server is unavailable At line:1 char:1 + Get-WinEvent -LogName application -MaxEvents 1 -ComputerName dc1 -Credential iam ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Get-WinEvent], EventLogException + FullyQualifiedErrorId : System.Diagnostics.Eventing.Reader.EventLogException, Microsoft.PowerShell.Commands.GetWinEventCommand
Other cmdlets, such as Get-Service and Get-Process, do not have a -credential parameter, and therefore the commands associated with cmdlets such as Get-Service or Get-Process impersonate the logged-on user. Such a command appears here:
PS C:\> Get-Service -ComputerName hyperv -Name bits Status Name DisplayName ------ ---- ----------- Running bits Background Intelligent Transfer Ser... PS C:\>
Just because the cmdlet does not support alternate credentials does not mean that the cmdlet must impersonate the logged-on user. Holding down the Shift key and right-clicking the Windows PowerShell icon from the taskbar brings up an action menu that allows you to run the program as a different user. This menu appears in Figure 4-2.
Figure 4-2 The menu from the Windows PowerShell console permits running with different security credentials.
The Run As Different User dialog box appears in Figure 4-3.
Figure 4-3 The Run As Different User dialog box permits entering a different user context.
Using the Run As Different User dialog box makes alternative credentials available for Windows PowerShell cmdlets that do not support the -credential parameter.
WinRM
Windows Server 2012 installs with Windows Remote Management (WinRM) configured and running to support remote Windows PowerShell commands. WinRM is Microsoft’s 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 CIM cmdlets. 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. 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 Windows PowerShell remoting on the client machine. When running the Enable-PSRemoting function, the function performs the following steps:
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 WSMAN 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 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 syntax of this command appears here:
Enable-PSRemoting -force
The use of the Enable-PSRemoting function in interactive mode appears here, 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 machine. 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 Windows PowerShell remoting is configured, use the Test-WSMan cmdlet to ensure that the WinRM remoting is properly configured and is accepting requests. A properly configured system replies with the information appearing here:
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. The output appearing here is from a domain controller running Windows 2008 with Windows PowerShell 2.0 installed and WinRM configured for remote access:
PS C:\> Test-WSMan -ComputerName dc1} 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: 2.0
If WinRM is not configured, an error returns from the system. Such an error from a Windows 8 client appears here:
PS C:\> Test-WSMan -ComputerName w8c10 Test-WSMan : <f:WSManFault xmlns:f="http://schemas.microsoft.com/wbem/wsman/1/wsmanfault" Code="2150859046" Machine="w8c504.iammred.net"><f:Message>WinRM cannot complete the operation. Verify that the specified computer name is valid, that the computer is accessible over the network, and that a firewall exception for the WinRM service is enabled and allows access from this computer. By default, the WinRM firewall exception for public profiles limits access to remote computers within the same local subnet. </f:Message></f:WSManFault> At line:1 char:1 + Test-WSMan -ComputerName w8c10 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (w8c10:String) [Test-WSMan], Invalid OperationException + FullyQualifiedErrorId : WsManError,Microsoft.WSMan.Management.TestWSManCommand
Keep in mind that configuring WinRM via the Enable-PSRemoting function does not enable the Remote Management firewall exception, and therefore PING commands will not work by default when pinging to a Windows 8 client system. This appears here:
PS C:\> ping w8c504 Pinging w8c504.iammred.net [192.168.0.56] with 32 bytes of data: Request timed out. Request timed out. Request timed out. Request timed out. Ping statistics for 192.168.0.56: Packets: Sent = 4, Received = 0, Lost = 4 (100% loss).
Pings to a Windows 2012 server, do however, work. This appears here:
PS C:\> ping w8s504 Pinging w8s504.iammred.net [192.168.0.57] with 32 bytes of data: Reply from 192.168.0.57: bytes=32 time<1ms TTL=128 Reply from 192.168.0.57: bytes=32 time<1ms TTL=128 Reply from 192.168.0.57: bytes=32 time<1ms TTL=128 Reply from 192.168.0.57: bytes=32 time<1ms TTL=128 Ping statistics for 192.168.0.57: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 0ms, Maximum = 0ms, Average = 0ms
Creating a remote Windows PowerShell session
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. This creates an interactive remote Windows PowerShell session on a target machine and uses the default remote endpoint. If you do not supply credentials, the remote session impersonates the currently logged on user The output appearing here illustrates connecting to a remote computer named dc1. Once the connection is established, the Windows PowerShell prompt changes to include the name of the remote system. Set-Location (which has an alias of sl) 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 prompt configured previously.
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:\>
The good thing is that when using the Windows PowerShell transcript tool via 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\PowerShell_ 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\PowerShell_ transcript.20120701124414.txt PS C:\>
Figure 4-4 displays a copy of the transcript from the previous session.
Figure 4-4 The Windows PowerShell transcript tool records commands and output received from a remote Windows PowerShell session.
If you anticipate making multiple connections to a remote system, use the New-PSSession cmdlet to create a remote Windows PowerShell session. New-PSSession permits you to store the remote session in a variable and provides you with the ability to enter and to 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 via 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 via the exit command. Next, the session is reentered, and the last process is retrieved. The session is exited once again. Finally, the Get-PSSession cmdlet retrieves Windows PowerShell sessions on the system, and all sessions are removed via 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:\>
Running a single Windows PowerShell command
If 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. You are still creating a remote session, but you are also removing the session. Therefore, if you have a lot of commands to run against the remote machine, a performance problem could arise. But for single commands, this technique works well. The technique is shown here, where the last process running on the Ex1 remote server appears:
PS C:\> Invoke-Command -ComputerName ex1 -ScriptBlock {gps | select -Last 1} Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName PSComputerNa me ------- ------ ----- ----- ----- ------ -- ----------- ------------ 224 34 47164 51080 532 0.58 10164 wsmprovhost ex1
If you have several commands, or if you anticipate making multiple connections, the Invoke-Command cmdlet accepts a session name or a session object in the same manner as the Enter-PSSession cmdlet. 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 the Windows PowerShell remote session is 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
Using Invoke-Command, you can run 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 PSCredential object for the remote connections. Finally, the Invoke-Command cmdlet is used to make connections to all of 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 commands and associated output appear here:
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:\>