Home > Sample chapters > Programming > Visual Studio and .NET

Using PowerShell Remoting and Jobs

Remoting in Microsoft Windows PowerShell 3.0 is much improved. This chapter from Windows PowerShell 3.0 Step by Step shows how to use Windows PowerShell remoting to connect to a remote system, run commands on a remote system, run commands in the background, receive the results of those and other background jobs, and keep the results from background jobs.

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

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

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

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:

  1. Starts or restarts the WinRM service

  2. Sets the WinRM service startup type to Automatic

  3. Creates a listener to accept requests from any Internet Protocol (IP) address

  4. Enables inbound firewall exceptions for WSMAN traffic

  5. Sets a target listener named Microsoft.powershell

  6. Sets a target listener named Microsoft.powershell.workflow

  7. 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

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:\>