With Great PowerShell Comes Great Responsibility
Windows administrators, like Unix or Linux administrators, look for ways to perform their duties with ease and elegance through automation. PowerShell allows administrators to gather information, change Registry parameters, work with Active Directory, manipulate services, look at events, work with Windows Management Instrumentation (WMI), and much more. PowerShell is a Windows administrator’s best friend.
This introduction to PowerShell outlines some of the more common problems that administrators face and how to solve them with PowerShell. You don’t need programming skills to use PowerShell, nor do you need to be adept at scripting of any kind. PowerShell handles the complex tasks behind the scenes by allowing you to work with a series of shortcut commands and parameters (switches) in the foreground.
In this first part, I introduce PowerShell information retrieval to you via the “Get” commands (cmdlets), which allow you to look at system information in a non-destructive way without changing anything. Think of the Get cmdlets as information browsing. In subsequent articles, you’ll see how to retrieve information and then change it.
Starting the PowerShell Environment
PowerShell cmdlets aren’t available in a standard CMD window. To invoke PowerShell, open a CMD window and then type powershell and Enter. You’ll see a response similar to the following:
C:\Users\khess>powershell
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.
PS C:\Users\khess>
The PS tells you that you’re in PowerShell and that PowerShell is ready to receive instructions in the form of cmdlets, which are shortcut names for programs that do your administrative bidding.
Before diving into a discussion of Powershell, check your PowerShell version by typing $Host at the PS prompt.
PS C:\Users\khess> $Host Name : ConsoleHost Version : 2.0 InstanceId : ccbc6963-c33e-4848-a8e5-aa1ccaf7d65c UI : System.Management.Automation.Internal.Host.InternalHostUserInterface CurrentCulture : en-US CurrentUICulture : en-US PrivateData : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy IsRunspacePushed : False Runspace : System.Management.Automation.Runspaces.LocalRunspace
You can also retrieve this information with the Get-Host cmdlet.
If the Version parameter doesn’t display 2.0, point your browser to the Microsoft support pages, scroll down the page, and download the appropriate components for your system. Once you’ve downloaded and installed the PowerShell 2.0 components, check your version again to be sure that you installed PowerShell 2.0.
PowerShell Syntax
All cmdlets have the following syntax:
PS> Verb-Noun [-Switch]
Switches and strings extend the power of the cmdlets but are optional.
For example, the cmdlet to list the running processes on your system, Get-Process, is in the Verb-Noun format. The cmdlets are always shown with uppercase and lowercase words, but they’re really not case sensitive. Case is used for illustrative purposes only.
Cmdlets have the form, Verb-Noun, and nouns are always singular. Get-Processes, while grammatically satisfying, is syntactically incorrect in PowerShell.
When you type Get-Process at the PS prompt, you should see a table listing all of your system’s running processes that looks similar to Task Manager’s Processes tab.
PowerShell on Your Local System
Before touching production systems with PowerShell cmdlets or scripts, you should practice and test with your local workstation. A virtual machine would be an even better sandbox in which to test. Never test on production systems.
Now look at the Get-Process cmdlet output. Is it in the format you want? If not, you can change it by passing parameters to switches that the cmdlet interprets then returns your changes to you.
The default Get-Process cmdlet reports system process information in the following format:
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 81 9 2392 3076 76 0.12 3996 AmIcoSinglun64 74 9 1464 2568 42 0.09 2172 armsvc 195 10 2380 2984 62 0.50 1164 atieclxx 102 9 2024 2380 34 0.08 960 atiesrxx 118 9 15648 15772 50 2664 audiodg 1337 528 42548 61444 284 2,611.69 1540 AvastSvc 286 29 14140 11580 162 17.88 3528 AvastUI 156 21 24200 45392 160 13.57 996 chrome 159 32 106848 124604 245 79.54 2720 chrome
Your processes display in descending alphabetical order by ProcessName. This is not that useful to an administrator who needs to know which process is consuming too much CPU time. You need to sort by CPU consumption in descending order so that you can see the processes consuming your CPU resources. If you use Linux, the top command is the equivalent of what you want to see here.
Issue the following cmdlet to sort by CPU time:
PS> Get-Process | Sort-Object -Descending -Property CPU Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 1073 73 86628 77748 418 ...58.57 2744 explorer 2214 125 222264 262652 654 ...88.10 2752 chrome 138 27 37056 12492 572 8,534.05 732 pcmontask 329 17 8744 14484 86 4,442.07 5992 WmiPrvSE 730 35 130680 123496 281 3,719.10 584 svchost
Your next question might be, “How would I know to run that cmdlet with that syntax to get the displayed results?” You wouldn’t unless you had some experience with PowerShell syntax and piping from one cmdlet to another.
To learn more advanced cmdlet syntax, like the one shown above, you have to write out the desired results from your script: List processes (easy) in order of highest CPU usage to lowest.
PowerShell gives you the ability to pipe the output of one cmdlet into the input of another cmdlet. If you’re also a Unix or Linux shell scripter, then you know the power of the pipe. If not, you’ll discover it with PowerShell.
However, before you can effectively pipe the output of one cmdlet into another, you need to know what the output is and how you want it configured when piped to the other cmdlet. You also need to know what your options are for filtering output from both cmdlets. An extensive Help system is available to assist you, which is outlined in more detail in the “PowerShell Help System” section later in this article.
You aren’t limited to processes on your system; you can also look at the status of services with a command such as:
PS> Get-Service Status Name DisplayName ------ ---- ----------- Running AdobeARMservice Adobe Acrobat Update Service Stopped AeLookupSvc Application Experience Stopped ALG Application Layer Gateway Service Running AMD External Ev... AMD External Events Utility Stopped AppIDSvc Application Identity Stopped Appinfo Application Information
You see that the Get-Service cmdlet returns a table displaying Status, Name, and DisplayName of all services on your system. Although this is useful information, if you want to look at a single service or a group of related services, a display of all services is a bit cumbersome. Try the following command:
PS> Get-Service -Name wmi* Status Name DisplayName ------ ---- ----------- Stopped wmiApSrv WMI Performance Adapter
Notice that I used the -Name switch to filter on the service name. If you try -DisplayName in your filter, when you enter -Status, an error is returned from the system because Status is not a parameter you can manipulate directly. It’s a bit advanced at this point to tell you why, so I’ll tell you that when you find such a property, you’ll have to use a workaround. One workaround is to use Sort-Object.
For example, to see a list of all services and their statuses filtered by status, enter:
PS> Get-Service | Sort-Object Status Status Name DisplayName ------ ---- ----------- Stopped QWAVE Quality Windows Audio Video Experience Stopped QBFCService Intuit QuickBooks FCS Stopped RasMan Remote Access Connection Manager Stopped RasAuto Remote Access Auto Connection Manager Stopped WwanSvc WWAN AutoConfig
PowerShell on Remote Systems
Using PowerShell on a local system is interesting and useful, but the real power of PowerShell is using it with remote systems. The beauty of PowerShell is that you don’t have to RDP or connect remotely in any direct way to run PowerShell commands on a remote system to which you have access: You just have to specify the remote computer’s name with the -ComputerName switch and the name of the remote system. If you do not specify a computer name, the command defaults to the local system.
For example, to see a list of running processes on a remote system, enter,
PS> Get-Process -ComputerName [Remote System Name ]
My remote Windows server name is XenApp1:
PS> Get-Process -ComputerName XenApp1 Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 237 11 2880 6616 47 1168 2XAgent 153 13 7604 10508 60 1116 2XController 264 10 8404 10832 58 1152 2XProxyGateway 110 8 7144 9564 54 1132 2XRedundancy 116 3 1016 4144 22 1188 appmgr
It works the same way for services:
PS> Get-Service -ComputerName XenApp1 -DisplayName Windows* Status Name DisplayName ------ ---- ----------- Running AudioSrv Windows Audio Stopped FontCache3.0.0.0 Windows Presentation Foundation Fon... Stopped idsvc Windows CardSpace Stopped MSIServer Windows Installer Stopped SharedAccess Windows Firewall/Internet Connectio... Stopped stisvc Windows Image Acquisition (WIA) Stopped UMWdf Windows User Mode Driver Framework Running W32Time Windows Time Running winmgmt Windows Management Instrumentation Running WinRM Windows Remote Management (WS-Manag... Running Wmi Windows Management Instrumentation ... Stopped WPFFontCache_v0400 Windows Presentation Foundation Fon... Running WSearch Windows Search
Similarly, you can run a cmdlet to view a subset of running services. In this example, I want to see all services that are related to the 2X service.
PS> Get-Service -ComputerName XenApp1 -Name 2X* Status Name DisplayName ------ ---- ----------- Running 2X Publishing A... 2X Publishing Agent Running 2X Redundancy S... 2X Redundancy Service Running 2X SecureClient... 2X SecureClientGateway Running 2X Terminal Ser... 2X Terminal Server Agent
Are you seeing the pattern of how PowerShell works for local versus remote systems?
Basically, any cmdlet that works locally will also work remotely if you specify -ComputerName <Remote Computer Name> in the syntax.
The PowerShell Help System
If you’re going to use PowerShell with any of its advanced features or write your own scripts, you’ll need to learn to use PowerShell’s Help system. To get help, you simply type the cmdlet Get-Help at the PS prompt. To find help with a specific cmdlet, use the Get-Help cmdlet followed by the command with which you need assistance:
PS> Get-Help Get-Process
The Help system looks like Unix-style man pages with the cmdlet name (NAME), a short description (SYNOPSIS), cmdlet syntax (SYNTAX), an extended description (DESCRIPTION), links and related commands (RELATED LINKS), and additional information (REMARKS).
To see examples of the cmdlet you’re interested in, type:
PS> Get-Help Get-Process -examples
Powershell also understands wildcards (* ?). For example, to see a list of all of the Get cmdlets, use:
PS> Get-Help Get*
To see a list of all possible Get cmdlets with a four-letter Noun, use:
PS> Get-Help Get????? Name Category Synopsis ---- -------- -------- Get-Verb Function Get-Verb [[-verb]] [-... Get-Help Cmdlet Displays information about Windo... Get-Date Cmdlet Gets the current date and time. Get-Host Cmdlet Gets an object that represents t... Get-Item Cmdlet Gets the item at the specified l...
You have to use five ? characters, one for the (-) and then four for the Noun portion.
Don’t ignore the related cmdlets in the RELATED LINKS portion of cmdlet help. For example, Get-Process has four related cmdlets that you might find useful:
- Start-Process
- Stop-Process
- Wait-Process
- Debug-Process
Summary
PowerShell is an important tool to add to your Windows adminsitrator toolbox. The more experience you gain with this essential tool, the better you’ll like it. PowerShell isn’t a traditional scripting language, although it does include many of the same attributes: variables, prompted input, redirected output, looping, and advanced decision making. If you’re new to PowerShell, practice with the Get cmdlets for a while before attempting any “Set” or other intrusive cmdlets.
Your assignment for this part of the series is to practice running Get cmdlets on your local system and on remote systems to view system information. If you want to venture further into this powerful language and its possibilities in your environment, please set up a virtual machine so you don’t irreversibly damage a live or production system.
Next month, I’ll show you how to manipulate services and processes and launch applications via PowerShell.