Using Remoting
When using remoting, three different modes can be used to execute commands. These modes are as follows:
1 to 1— Referred to as Interactive mode. This mode enables you to remotely manage a machine similar to using an SSH session.
Many to 1— Referred to as the Fan-In mode. This mode allows multiple administrators to manage a single host using an interactive session.
1 to Many— Referred to as the Fan-Out mode. This mode allows a command to execute across a large number of machines.
More information about each mode is provided in the following sections.
Interactive Remoting
With interactive remoting,
the PowerShell session you are executing commands within looks and feels
very much like an SSH session, as shown in the following example:
PS C:\> enter-pssession abc-util01
[abc-util01]: PS C:\Users\administrator.COMPANYABC\Documents>
The key to achieving this mode of remoting is a PowerShell feature
called a runspace. Runspaces by definition are instances of the System.Management.Automationcmd.exe, and so on). In other class, which defines the PowerShell session and its host program (Windows PowerShell host, words, a runspace is an execution environment in which PowerShell runs.
Not widely discussed in
PowerShell 1.0, runspaces in PowerShell 2.0 are the method by which
commands are executed on local and remote machines. When a runspace is
created, it resides in the global scope and it is an environment upon
itself, which includes its own properties, execution polices, and
profiles. This environment persists for the lifetime of the runspace,
regardless of the volatility of the host machine’s environment.
Being
tied to the host program that created it, a runspace ceases to exist
when the host program is closed. When this happens, all aspects of the
runspace are gone, and you can no longer retrieve or use the runspace.
However, when created on a remote machine, a runspace will remain until
it is stopped.
To create a runspace on a machine,
you can use two cmdlets. The first cmdlet, Enter-PSSession, is used to
create an interactive PowerShell session. This is the cmdlet that was
shown in the previous example. When this cmdlet is used against a remote
machine, a new runspace (PowerShell process) is created and a
connection is established from the local machine to the runspace on the
remote computer. If executed against the local machine, a new runspace
(PowerShell process) is created and connection is established back to
the local machine. To close the interactive session, you would use the
Exit-PSSession cmdlet or the exit alias.
Fan-In Remoting
Fan-In remoting is named
in reference to the ability for multiple administrators to open their
own runspaces at the same time. In other words, many administrators can
“Fan-In” from many machines into a single machine. When connected, each
administrator is then limited to the scope of their own runspace. This
partitioning of access can be achieved thanks to the new PowerShell 2.0
security model, which allows for the creation of restricted shells and
cmdlets.
However, the steps needed to
fully utilize the new security model require a degree of software
development using the .NET Framework. The ability of being able to
provide secure partitioned remote management access on a single host to a
number of different administrators is a very powerful feature. Usage
could range from a web hosting company wanting to partition remote
management access to each customer for each of their websites to
internal IT departments wanting to consolidate their management consoles
on a single server.
Fan-Out Remoting
Fan-Out remoting is named
in reference to the ability to issue commands to a number of remote
machines at once. When using this method of remoting, command(s) are
issued on your machine. These commands then “Fan-Out” and are executed
on each of the remote machines that have been specified. The results
from each remote machine are then returned to your machine in the form
of an object, which you can then review or further work with—in other
words.
Ironically enough,
PowerShell has always supported the concept of Fan-Out remoting. In
PowerShell 1.0, Fan-Out remoting was achieved using WMI. For example,
you could always import a list of machine names and then use WMI to
remotely manage those machines:
PS C:\> import-csv machineList.csv | foreach {Get-WmiObject Win32_NetworkAdapterConfiguration -computer $_.MachineName}
Although the ability to
perform Fan-Out remoting in PowerShell 1.0 using WMI was a powerful
feature, this form of remoting suffered in usability because it was
synchronous in nature.
In other words, once a command had been issued, it was executed on each
remote machine one at a time. While this happened, further command
execution had to wait until the command issued had finished being
executed on all the specified remote machines.
Needless to say,
attempting to synchronously manage a large number of remote machines can
prove to be a challenging task. To address this challenge in PowerShell
2.0, the product team tweaked the remoting experience such that Fan-Out
remoting could be done asynchronously. With these changes, you could
still perform remote WMI management, as shown in the previous example.
However, you can also asynchronously execute remote commands using the
following methods:
Executing the command as a background job
Using the Invoke-Command cmdlet
Using the Invoke-Command cmdlet with a reusable runspace
The first method, a background
job, as its name might suggest, allows commands to be executed in the
background. Although not truly asynchronous, a command that is executed
as a background job enables you to continue executing additional
commands while the job is being completed. For example, to run the
previously shown WMI example as a background job, you can simply add the
AsJob parameter for the Get-WmiObject cmdlet:
PS C:\> import-csv machineList.csv | foreach {Get-WmiObject Win32_NetworkAdapterConfiguration -computer $_.MachineName -asjob}
With the AsJob parameter (new in PowerShell 2.0) being used, each time the Get-WmiObject cmdet is called in the foreach
loop, a new background job is created to complete execution of the
cmdlet. This example shows how background jobs can be used to
achieve asynchronous remote command execution when using WMI.
The second method to
asynchronously execute remote commands is by using the new cmdlet called
Invoke-Command. This cmdlet is new in PowerShell 2.0, and it enables
you to execute commands both locally and remotely on machines—unlike
WMI, which uses remote procedure calls (RPC) connections to remotely
manage machines. The Invoke-Command cmdlet utilizes WinRM to push the
commands out to each of the specified “targets” in an asynchronous
manner.
To use the cmdlet, two primary parameters need to be defined. The first parameter, ScriptBlock, is used to specify a scriptblock, which contains the command to be executed. The second parameter, ComputerName
(NetBIOS name or IP address), is used to specify the machine or
machines to execute the command that is defined in the scriptblock. For
example:
PS C:\> invoke-command -scriptblock {get-process} -computer sc1-infra01,sc1-infra02
Additionally,
the Invoke-Command cmdlet also supports a set of parameters that make
it an even more powerful vehicle to conduct remote automation tasks
with. These parameters are described in Table 2.
Table 2. Important Invoke-Command Cmdlet Parameters
Parameter | Details |
---|
AsJob | Used to execute the command as a background job |
Credential | Used to specify alternate credentials that are used to execute the specified command(s) |
ThrottleLimit | Used to specify the maximum number of connections that can be established by the Invoke-Command cmdlet |
Session | Used to execute the command in the specified PSSessions |
As discussed previously, the AsJob parameter is used to execute the specified command as a background job. However, unlike the Get-WmiObject cmdlet, when the AsJob
parameter is used with the Invoke-Command cmdlet, a background job is
created on the client machine, which then spawns a number of child
background job(s) on each of the specified remote machine(s). Once
execution of a child background job is finished, the result(s) are
returned to the parent background job on the client machine.
Needless to say, if there are a large number of remote machines defined using the ComputerName
parameter, the client machine might become overwhelmed. To help prevent
the client machine or your network from drowning in an asynchronous
connection storm, the Invoke-Command cmdlet will, by default, limit the
number of concurrent remote connections for an issued command to 32. If
you want to tweak the number of concurrent connections allowed, you
would use the ThrottleLimit parameter.
Note
The ThrottleLimit parameter can also be used with the New-PSSession cmdlet.
An important concept to
understand when using the Invoke-Command cmdlet is how it actually
executes commands on a remote machine. By default, this cmdlet will set
up temporary runspace for each of the targeted remote machine(s). Once
execution of the specified command has finished, both the runspace and
the connection resulting from that runspace are closed. This means,
irrespective of how the ThrottleLimit
parameter is used, if you are executing a number of different commands
using the Invoke-Command cmdlet at the same time, the actual number of
concurrent connections to a remote machine is the total number of times
you invoked the Invoke-Command cmdlet.
Needless to say, if you want to reuse the same existing connection and runspace, you need to use the Invoke-Command cmdlet’s Session parameter. However, to make use of the parameter
requires an already existing runspace on the targeted remote
machine(s). To create a persistent runspace on a remote machine, you
would use the New-PSSession cmdlet, as shown in the following example:
PS C:\> new-pssession -computer "sc1-infra01","sc1-ad01"
After executing the
previous command, two persistent runspaces on each of the specified
targets will have been created. These runspaces can then be used to
complete multiple commands and even share data between those commands.
To use these runspaces, you need to retrieve the resulting runspace
object(s) using the Get-PSSession cmdlet and then pass it into the
Invoke-Command cmdlet. For example:
PS C:\> $Sessions = new-pssession -computer "sc1-infra01","sc1-ad01"
PS C:\> invoke-command -scriptblock {get-service "W32Time"} -session $Sessions | ft
PSComputerName, Name, Status
PSComputerName Name Status
------------ ---- ------
sc1-ad01 W32Time Running
sc1-infra01 W32Time Running
First, the $Sessions variable is used to store the two resulting runspace objects that are created using the New-PSSession cmdlet. Next, the $Sessions variable is then defined as the argument for the Session parameter of the Invoke-Command cmdlet. By doing this, the command that is defined as the argument for the ScriptBlock parameter is executed within each of the runspaces represented by the $Sessions
variable. Finally, the results from the command executed within each of
the runspaces is returned and piped into the Format-Table cmdlet to
format the output. In this case, the output shows the current status of
the W32Time service on each of the specified remote machines.
After you have finished
executing commands, it’s important to understand that the runspaces that
were created will remain open until you close the current PowerShell
console. To free up the resources being consumed by a runspace, you need
to delete it using the Remove-PSSession cmdlet. For example, to remove
the runspaces contained in the $Sessions variable, you would pass that variable into the Remove-PSSession cmdlet:
PS C:\> $Sessions | remove-pssession
Using the New-Object Cmdlet
The New-Object cmdlet is used
to create both .NET and COM objects. To create an instance of a .NET
object, you simply provide the fully qualified name of the .NET class
you want to use, as shown here:
PS C:\> $Ping = new-object Net.NetworkInformation.Ping
By using the New-Object
cmdlet, you now have an instance of the Ping class that enables you to
detect whether a remote computer can be reached via Internet Control Message Protocol (ICMP). Therefore, you have an object-based version of the Ping.exe command-line tool.
To an instance of a COM
object, the comObject parameter is used. To use this parameter, define
its argument as the COM object’s programmatic identifier (ProgID), as
shown here:
PS C:\> $IE = new-object -comObject InternetExplorer.Application
PS C:\> $IE.Visible=$True
PS C:\> $IE.Navigate("www.cnn.com")