Scripting with Windows PowerShell Part 1
Working with processes, services, and event logs
Part 1 of a 5 part series.
Windows 7 is the only operating system that has Windows PowerShell and PowerShell ISE (developer environment) fully installed. The rest of the operating systems either have nothing installed or just have the DOS box style command prompt which is blue instead of black - woo-who! The best way to install it or the missing components is via Windows Update.
Ed Wilson, the person who did the webcast (of which this is a transcript), has his own blog where he evangelises PowerShell. It’s updated everyday and contains some useful stuff like Use PowerShell to Copy a Table Between Two SQL Server Instances.
There is a section of his blog called Scripting Wife that is basically instructions on how to do things but with screen shots where he has tried to make it really simple. I think the title is a little condescending but at least there is something. One of the articles talks you through how to set up PowerShell in case you don’t have Windows 7 installed.
The shell can be loaded via Start -> All programs -> Accessories -> Windows PowerShell.
Load in the blue console Windows PowerShell. Microsoft have added the Unix equivalent commands to the shell for some of the normal DOS commands.
For the most part PowerShell is just like using the normal (black) command shell. The TAB key acts as a better file name completion, so get half way through a directory path, hit TAB and the shell will cycle through possible files which match that sequence. There is also up/down arrow history.
Try it out now. Open a PowerShell command prompt and type “get-c” (without the quotes) then hit the TAB button. The “get-c” will complete firstly to Get-ChildItem and pressing TAB again will move you one to Get-Command. If you were to carry on you would get Get-ComputerRestorePoint, Get-Content, Get-Counter, Get-Credential, Get-Culture before cycling back to Get-ChildItem. If you go passed the command you were looking for then you can press SHIFT+TAB to go backwards through the list. Play with it by typing another “get-” and hitting TAB and see how the different commands are completed.
If we want to find out about a particular command then we can use the Get-Command command. For example we would like to see what commands are related to processes. Type get-co TAB which will complete to Get-Command. Press the space bar to move to the first argument on the command line. Type “-” and then hit TAB to cycle through the available options that this command supports. The first one is -Name, then hit TAB again to get -Verb and again to get -Noun. Add another space so that we can add a option parameter, enter “*proc*” so the command line reads:
Windows | Unix |
---|---|
dir | ls |
type | cat |
cls | clear |
Get-Command -Noun *proc*then press return to issue the command and you will get the commands along with their options.
CommandType Name Definition ----------- ---- ---------- Cmdlet Debug-Process Debug-Process [-Name] <String[]> [-Verbose] [-De... Cmdlet Get-Process Get-Process [[-Name] <String[]>] [-ComputerName ... Cmdlet Start-Process Start-Process [-FilePath] <String> [[-ArgumentLi... Cmdlet Stop-Process Stop-Process [-Id] <Int32[]> [-PassThru] [-Force... Cmdlet Wait-Process Wait-Process [-Name] <String[]> [[-Timeout] <Int...There are 5 process related Cmdlets (which are command line add-ons). Enter the Get-Process command. It will display information about each process.
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 148 119 3292 13356 85 0.05 1416 albd_server 157 9 1972 6188 63 0.09 1108 atieclxx 68 8 2060 7580 74 0.06 1256 Notepad 92 8 2612 9712 77 12.20 2324 Notepad 149 11 17116 16816 48 3668 audiodgThe table displays the number of handles, private memory (in kilobytes), working sat?, virtual memory, CPU time in seconds, process identifier and process name. Some information is missing because they require elevated privileges to get that information. If you want all the information you must Run As Administrator. The opposite of Get-Process is Stop-Process, so let’s load a process we can kill. Launch notepad by typing notepad on the command prompt. Check it is running with Get-Process notep*. There are 2 ways we can kill the notepad process: one at a time or all of the running notepad processes together.
Stop-Process 1234 Stop-Process -id 1234where 1234 is the id of the process. We can also use the Get-process notep* to pre-filter the processes we would like to stop. What do you think would happen if we ran the following command.
Get-process notep* | Stop-ProcessWe can find out by asking “What if":
Get-process notep* | Stop-Process -WhatIf
What if: Performing operation "Stop-Process" on Target "Notepad2 (1256)". What if: Performing operation "Stop-Process" on Target "Notepad2 (2324)". What if: Performing operation "Stop-Process" on Target "Notepad2 (4648)".This is the biggest difference between Unix shell and Windows PowerShell. Under Unix the output of one file maybe the input of any other file but the pipe conduit only delivers the flat text output and retrieves the flat text input. Under Windows PowerShell the meaning behind each line is carried through the pipe. In the Get-Process/Stop-Process example the Stop-Process knew that the ID part of the Get-Process column was the key to use when it came to stopping processes. Now that we can launch processes and kill them we probably want to learn a bit about going over our passed command history. We can use the Get-Command command to find out about history in the same way we did above:
Get-Command -Noun *history*
CommandType Name Definition ----------- ---- ---------- Cmdlet Add-History Add-History [[-InputObject] <psobject []>] [-Pass... Cmdlet Clear-History Clear-History [[-Id] <int32 []>] [[-Count] <int32 ... Cmdlet Get-History Get-History [[-Id] <Int64[]>] [[-Count] <int32>]... Cmdlet Invoke-History Invoke-History [[-Id] <string>] [-Verbose] [-Deb...Run the Get-History cmdlet which will give you a list of all the commands you have issued. History is something that is used all the time and so there are several alias’ for Get-History. These may be found by issuing the alias command:
alias h*to give us:
CommandType Name Definition ----------- ---- ---------- Alias h Get-History Alias history Get-HistoryRunning the Get-History command will list all the commands you have issued in the current shell:
Id CommandLine -- ----------- 1 dir 2 cls 3 clear 4 Get-Process 5 notepad 6 notepadNow we can use the
Invoke-History -id 4 Invoke-History 4which will run Get-Process. Fiddling around with the history commands to invoke previously issued commands can be a little time consuming; you might find it easier to get the history and highlight the command you would like to run again with the mouse and right click twice to copy the highlighted text to the clipboard and paste into the command window. Let’s look at a couple of useful PowerShell system commands. Get-Service Lists all the services and has an output similar to below:
Get-Service
Status Name DisplayName ------ ---- ----------- Stopped AeLookupSvc Application Experience Running Albd Atria Location Broker Stopped ALG Application Layer Gateway ServiceThe list of services is kind of long so let’s filter it to only show services that have a Status of Running. Let’s take a look at the command:
Get-Service | where { $_.status -eq “Running” }Where is PowerShell’s version of grep with line object knowledge. Ed Wilson says the $_ refers to each service but that can’t be right, it actually refers to each line (or as we discovered earlier each object line). If you do a TAB command completion after the dot after the $_, then you get commands like $_.Length, $_.CompareTo(, $_.Contains( and a whole host of other test conditions and attributes. So I think that if it recognises the “.status” as a column name it uses that, otherwise it sees if there are any predefined functions. The code between the curly braces is known as a script block or a code block or “like a wavy curvy fried thingy, dude” - Thanks Ed. The block between the braces “{}” is the filter applied to each object (line).
Status Name DisplayName ------ ---- ----------- Running Albd Atria Location Broker Running AMD External Ev... AMD External Events Utility Running AppMgmt Application Management Running AudioEndpointBu... Windows Audio Endpoint BuilderA bit of testing around and we can use the contains builtin function. Strangely the search text (Installer) is case-sensitive! unlike all the other commands.
Get-Service | where { $_.displayname.contains("Installer") }
Status Name DisplayName ------ ---- ----------- Stopped AxInstSV ActiveX Installer (AxInstSV) Stopped msiserver Windows Installer Stopped TrustedInstaller Windows Modules InstallerGet-EvenLog Faster way to look at system events.
Get-EventLog -LogName application -Newest 3Ed Wilson spent over a minute talking about how running this command was faster that going into the control panel, loading the event view and finding the application event log. Well no shit Sherlock! “application” can be replaced by “system” for system logs. Get-Help This is basically Unix manual. The layout is the same too! With the same headings too: NAME, SYNOPSIS, SYNTAX, DESCRIPTION, RELATED LINKS and REMARKS.
Get-Help Get-ProcessIf you look at the help for Get-Process you will see -ComputerName <string[]> in the SYNTAX section which means that you can run this command against other machines in the domain. There is no where on the command line for me to add my credentials so the program is going to impersonate me. The command will run on local machines or remote machines but not against an untrusted network. In the Unix manual there is usually an EXAMPLES section at the end, but PowerShell’s Get-Help has split it out as an extra command.
Get-Help -Examples Get-ProcessThere are 9 examples of Get-Process showing how to filter the information, store it, format it, get file versions, modules that are loaded with the process.
Get-Help -Full Get-Process | moreSame as -Examples but more detailed. There is so much scrolling off the screen that I have piped it into the more command which handles the text in a pager fashion.
Help -Full Get-ProcessHelp is short for Get-Help except for it adds the more pager on the end automatically. End of session questions and answers Q: What do I need to make calls using Windows PowerShell? A: Window PowerShell v2+ to do remote calls A: PowerShell supports WMI so you can run remote commands by using that instead. Q: Can you change the privileges of a command that is running? A: No, but you can use the RunAs(.exe) to emulate the Unix sudo command. Q: Group Policy for administration files do not come installed on Windows 7 by default? A: True Q: What version of PowerShell am I running? A: There is an environment variable to tell you.
$PSVersionTable
Name Value ---- ----- CLRVersion 2.0.50727.4959 BuildVersion 6.1.7600.16385 PSVersion 2.0 WSManStackVersion 2.0 PSCompatibleVersions {1.0, 2.0} SerializationVersion 1.1.0.1 PSRemotingProtocolVersion 2.1The environment variable is a set of interrogate’able objects commands can be teased apart. For example
$PSVersionTable.BuildVersion
Major Minor Build Revision ----- ----- ----- -------- 6 1 7600 16385
$PSVersionTable.BuildVersion.Major
6Q: PowerShell vs Command line A: It’s better (but surrounded by 2 minutes of waffle!) Q: Can you list all the PowerShell variables? A:
dir variable:
Name Value ---- ----- $ ^ ? False ^ ^ _ args {} ConfirmPreference High ConsoleFileName DebugPreference SilentlyContinueSome of these can be set up in your PowerShell profile. A useful one is MaximumHistoryCount for the number of commands your history will store.
No feedback yet
Form is loading...