Understanding Windows PowerShell
Windows PowerShell comes in two flavors—the first is an interactive console (sort of like a KORN or a BASH console in the UNIX world) that is built into the Windows command prompt. The Windows PowerShell console makes it simple to type short commands and to receive sorted, filtered, formatted results. These results easily display to the console, but can redirect to XML, CSV, or text files. The Windows PowerShell console offers several advantages, such as speed, low memory overhead, and a comprehensive transcription service that records all commands and command output.
There is also the Windows PowerShell ISE. The Windows PowerShell ISE is an integrated scripting environment, but this does not mean you must use it to write scripts. In fact, many Windows PowerShell users like to write their script in the Windows PowerShell ISE to take advantage of the color syntax highlighting, drop-down lists, and automatic parameter revelation features. In addition, the Windows PowerShell ISE has a feature called the Show Command Add-On, which permits using a mouse to create Windows PowerShell commands from a graphical environment. After created, the command runs directly or is added to the script pane (the choice is up to you). For more information about using the Windows PowerShell ISE, see Chapter 10, Using the Windows PowerShell ISE.
Note For simplicity, when working with single commands, I show the command and results from within the Windows PowerShell console. But keep in mind that all of the commands also run from within the Windows PowerShell ISE. Whether the command runs in the Windows PowerShell console, in the Windows PowerShell ISE, as a scheduled task, or as a filter for Group Policy, PowerShell is PowerShell is PowerShell. In its most basic form, a Windows PowerShell script is simply a collection of Windows PowerShell commands.
Working with Windows PowerShell
In Windows Server 2012 or Windows 8, Windows PowerShell 3.0 already exists. In Windows 8, you only need to type the first few letters of the word PowerShell on the Start screen before Windows PowerShell appears as an option. The following image illustrates this point. I only typed pow before the Start screen search box changed to offer Windows PowerShell and an option.
Because navigating to the Start screen and typing pow each time I want to launch Windows PowerShell is a bit cumbersome, I prefer to pin the Windows PowerShell console (and the Windows PowerShell ISE) to the Start page and to the Windows desktop taskbar. This technique of pinning shortcuts to the applications provides single-click access to Windows PowerShell from wherever I may be working.
Understanding the basics of cmdlets
All Windows PowerShell cmdlets behave basically the same way. There are some idiosyncrasies between cmdlets from different vendors, or from teams at Microsoft, but in general, when you understand the way that Windows PowerShell cmdlets work, you can transfer the knowledge to other cmdlets, platforms, and applications.
To call a Windows PowerShell cmdlet, you type it on a line in the Windows PowerShell console. To modify the way the cmdlet retrieves or displays information, you supply options for parameters that modify the cmdlet. Many of these parameters are unique and apply only to certain cmdlets. However, some parameters are applicable to all Windows PowerShell cmdlets. In fact, these cmdlets are part of the strength of the Windows PowerShell design. Called “common parameters,” the parameters that are supported by all Windows PowerShell cmdlets are listed in the next section.
Common Windows PowerShell parameters
All Windows PowerShell cmdlets support common parameters. Each of the common parameters also permits the use of an alias for the parameter. The aliases for each parameter appear in parentheses behind the parameter name in the following lists.
- Verbose (vb)
- Debug (db)
- WarningAction (wa)
- WarningVariable (wv)
- ErrorAction (ea)
- ErrorVariable (ev)
- OutVariable (ov)
- OutBuffer (ob)
If a Windows PowerShell cmdlet changes system state (such as stopping a process or changing the startup value of a service), the following two additional parameters become available:
- WhatIf (wi)
- Confirm (cf)
Using the Verbose parameter
As an example of using a Windows PowerShell common parameter, we can use the –Verbose parameter to obtain additional information about the action that a cmdlet performs. The following command stops all instances of the Notepad.exe process running on the local system, and there is no output from the command:
PS C:\> Stop-Process -Name notepad
PS C:\>
PS C:\>
To see what processes stop in response to the Stop-Process cmdlet, use the –Verbose common parameter. In the following example, two separate Notepad.exe processes stop in response to the Stop-Process cmdlet. Because the cmdlet uses the –Verbose common parameter, detailed information about each process appears in the output.
PS C:\> Stop-Process -Name notepad -Verbose
VERBOSE: Performing operation "Stop-Process" on Target "notepad (5564)".
VERBOSE: Performing operation "Stop-Process" on Target "notepad (5924)".
PS C:\>
VERBOSE: Performing operation "Stop-Process" on Target "notepad (5564)".
VERBOSE: Performing operation "Stop-Process" on Target "notepad (5924)".
PS C:\>
Using the ErrorAction parameter
When you use the Stop-Process cmdlet to stop a process, if there is not an instance of the specified process running, a nasty error message displays on the Windows PowerShell console. In the following example, the Stop-Process cmdlet attempts to stop a process named notepad.exe, but there are no instances of the notepad.exe process running. Therefore, an error message displays as follows:
PS C:\> Get-Process -Name notepad
Get-Process : Cannot find a process with the name "notepad". Verify the process
name and call the cmdlet again.
At line:1 char:1
+ Get-Process -Name notepad
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (notepad:String) [Get-Process], Proce
ssCommandException
+ FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Comma
nds.GetProcessCommand
PS C:\>
Get-Process : Cannot find a process with the name "notepad". Verify the process
name and call the cmdlet again.
At line:1 char:1
+ Get-Process -Name notepad
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (notepad:String) [Get-Process], Proce
ssCommandException
+ FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Comma
nds.GetProcessCommand
PS C:\>
If you know (or at least suspect), that a process is not running, but you would like to verify this, you can use the –ErrorActioncommon parameter. To hide error messages arising from the Get-Process cmdlet, supply a value of SilentlyContinue for the –ErrorAction parameter prior to running the cmdlet. This technique is shown here:
PS C:\> Get-Process -Name notepad -ErrorAction SilentlyContinue
PS C:\>
PS C:\>
Note The previous command appears to be really long, but keep in mind that Tab expansion makes this easy to type correctly. In fact, the previous command is:
Get-Pro<tab><space>-n<tab><space>notepad<space>-e<tab><space>s<tab>
You can use the parameter alias –EA instead of typing –ErrorAction (although with Tab expansion,
it is exactly the same number of keystrokes to shorten the command):
it is exactly the same number of keystrokes to shorten the command):
–E<tab> or –EA
In addition, when you work with the Get-Process cmdlet, the default parameter set is Name. This means that the –Nameparameter from Get-Process is the default parameter; and therefore, Get-Process interprets any string in the first position as the name of a process. The revised command is shown here:
PS C:\> Get-Process notepad -ea SilentlyContinue
PS C:\>
If you are not certain about valid values for the –ErrorAction parameter, you can supply anything to the parameter and then carefully read the resulting error message. In the text of the error message, the first two lines state that Windows PowerShell is unable to convert the value to the System.Management.Automation.ActionPreference type. The fourth line of the error message lists allowed values for the –ErrorAction parameter. The allowed values are SilentlyContinue, Stop, Continue, Inquire, andIgnore. This technique of forcing an error message is shown in the following image:
Introduction to the pipeline
The Windows PowerShell pipeline takes the output from one command and sends it as input to another command. By using the pipeline, you are able to do things like find all computers in one specific location and restart them. There are two commands in this request:
- Find all the computers in a specific location
- Restart each of the computers.
Passing the objects from one command to a new command makes Windows PowerShell easy to use inside the console because you do not have to stop and parse the output from the first command before taking action with a second command.
Windows PowerShell passes objects down the pipeline. This is one way that Windows PowerShell becomes very efficient. It takes an object (or group of objects) from the results of running one command, and it passes those objects to the input of another command. By using the Windows PowerShell pipeline, it is not necessary to store the results of one command into a variable, and then call a method on that object to perform an action. For example, the following command disables all network adapters on my Windows 8 laptop.
Get-NetAdapter | Disable-NetAdapter
Note Windows PowerShell honors the Windows security policy. Therefore, to disable a network adapter, Windows PowerShell must run with Admin credentials. For more information about starting Windows PowerShell with Admin credentials, refer to Chapter 1 in Windows PowerShell 3.0 First Steps.
In addition to disabling all network adapters, you can enable them. To do this, use the Get-NetAdapter cmdlet and pipe the results to the Enable-NetAdapter cmdlet as shown here:
Get-NetAdapter | Enable-NetAdapter
If you want to start all of the virtual machines in Windows 8 (or Windows Server 2012), use the Get-VM cmdlet, and pipe the resulting virtual machine objects to the Start-VM cmdlet:
Get-VM | Start-VM
To shut down all of the virtual machines, use the Get-VM cmdlet, and pipe the resulting virtual machine objects to the Stop-VMcmdlet:
Get-VM | Stop-VM
In each of the previous commands, an object (or group of objects) resulting from one command pipes to another cmdlet for further action.
Sorting output from a cmdlet
The Get-Process cmdlet generates a nice table view of process information in the Windows PowerShell console. The default view appears in ascending alphabetical process name order. This view is useful to help find specific process information, but it hides important details, such as which process uses the least or the most virtual memory.
To sort the output from the process table, pipe the results from the Get-Process cmdlet to the Sort-Object cmdlet and supply the property on which to sort to the –Property parameter. The default sort order is ascending (that is smallest numbers appear at the top of the list). The following command sorts the process output by the amount of virtual memory that is used by each process. The processes that consumes the least amount of virtual memory appear at the top of the list.
Get-Process | Sort-Object -Property VM
If you are interested in which processes consume the most virtual memory, you may want to reverse the default sort order. To do this, use the –Descending switch parameter as shown here:
Get-Process | Sort-Object -Property VM –Descending
The command to produce the sorted list of processes for the virtual memory, and the associated output from the command are shown in the image that follows.
It is possible to shorten the length of Windows PowerShell commands that use the Sort-Object cmdlet. The Sort command is an alias for the Sort-Object cmdlet. A cmdlet alias is a shortened form of the cmdlet name that Windows PowerShell recognizes as a substitute for the complete cmdlet name. Some aliases are easily recognizable (such as Sort for Sort-Object or Select forSelect-Object). Other aliases must be learned, such as ? for the Where-Object (most Windows users expect ? to be an alias for the Get-Help cmdlet).
In addition to using an alias for the Sort-Object cmdlet name, the –Property parameter is the default parameter that the cmdlet utilizes. Therefore, it can be left out of the command. The following command uses the shortened syntax to produce a list of services by status:
Get-Service | sort status
It is possible to sort on more than one property. You need to be careful doing this because at times it is not possible to sort additional properties. For services, a multiple sort makes sense because there are two broad categories of status: Running and Stopped. It makes sense to attempt to organize the output further to facilitate finding particular stopped or running services.
One way to facilitate finding services is to sort alphabetically the DisplayName property of each service. The script that follows sorts the service objects that are obtained via the Get-Service cmdlet by the status, and then by DisplayName from within the status. The output appears in descending fashion instead of the default ascending sorted listing.
Get-Service | sort status, displayname –Descending
The command to sort services by Status and DisplayName, and the output from the command are shown in the following image.