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.
Windows | Unix |
dir | ls |
type | cat |
cls | clear |
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:
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 audiodg
The 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 1234
where 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-Process
We 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-History
Running 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 notepad
Now we can use the
Invoke-History -id 4
Invoke-History 4
which 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 Service
The 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 Builder
A 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 Installer
Get-EvenLog
Faster way to look at system events.
Get-EventLog -LogName application -Newest 3
Ed 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-Process
If 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-Process
There 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 | more
Same 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-Process
Help 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.1
The 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
6
Q: 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 SilentlyContinue
Some of these can be set up in your PowerShell profile. A useful one is
MaximumHistoryCount for the number of commands your history will store.