Summary: Use the Windows PowerShell cmdlet, Select-String, to view the contents of a log file.
Hey, Scripting Guy! I have a log file that I created by dumping process information from Get-Process. It is quite long, and I am trying to use Select-String to find the number of instances of a certain process. The problem is that when I find the instance, I do not know what the columns mean. I am wondering what I can do to get the column headers in addition to the process information to show up in my output. I know I can do this with a script, but I don’t want to write a script to accomplish this task. Can you help?
—BU
Hello BU,
Microsoft Scripting Guy, Ed Wilson, is here. Well, I am sore again. It seems that when I go see my trainer, I come away sore. After the weekend, I start to feel good, and then BOOM!—I go back and I am sore all over again. And I do mean sore all over.
Anyway, the Scripting Wife bought me a nice one-pound bag of English Breakfast tea, so I am sitting here, trying to cool down, sipping a cup of English Breakfast tea with a cinnamon stick in it, and thinking about rejoining the world of the living. I am checking my email sent to scripter@microsoft.com, and BU, I ran across your email. The answer is, "Sure, it can be done. In fact, it is not too hard at all."
First the log file
You say that you have a log file you created by using Get-Process. I am assuming the command you used was something like the following:
Get-Process >> C:\FSO|MyProcesses.txt
The resulting log file is shwon here:
If I use the Select-String cmdlet to read the log file and to look for instances related to the iexplore process, I might use a command such as this:
Get-Content C:\fso\myprocesses.txt | Select-String 'iexplore'
The command and the output from the command are shown here:
The problem with this command, is that I cannot tell what the columns of numbers mean. Also, it is more work than is required. I do not need to use Get-Content first. I can simply use Select-String to find the information I need.
One way to get column headings
I can use two commands to get the column headings. The first is to use the Get-Content cmdlet and return only the first two lines from the file. This will give me the column headings. The command is shown here:
Get-Content C:\fso\myprocesses.txt -TotalCount 2
I can then use the previous command to display the column details, as shown here:
It is not ideal, but it does give me an idea of what is going on, and I can line up the column headings well enough to decipher the output. So, this will work.
Simplify things
I said that I do not need to resort to Get-Content at all. In fact, I can use Select-String to parse the file and find the information all at the same time. To do this, all I need to do is to specify the path to the file, for example:
Select-String -Path C:\fso\myprocesses.txt -Pattern iexplore
The command and the output are shown here (note that this command includes the file and the line number where the match occurred).
I still need to obtain the headers from the file to be able to make sense of the output. I could go back to using Get-Content, but the output would not be quite as readable. A better way is to use the regular expression OR pattern. I know that one of the columns includes the word Handles. So I can specify my pattern to be iexplore OR Handles. Here is the command I use:
Select-String -Path C:\fso\myprocesses.txt -Pattern "(iexplore|Handles)"
The command and the output are shown here:
The output is a little better, and the columns line up pretty well. I may decide to leave it at this. But if I do not need the Line number field or the Path field, I can clean up the output. To do this, I need to know the properties of the MatchInfo object. I get these from Get-Member as shown here:
Select-String -Path C:\fso\myprocesses.txt -Pattern "(iexplore|Handles)" | get-member -MemberType Properties
TypeName: Microsoft.PowerShell.Commands.MatchInfo
Name MemberType Definition
---- ---------- ----------
Context Property Microsoft.PowerShell.Commands.MatchInfoContext Context {get;set;}
Filename Property string Filename {get;}
IgnoreCase Property bool IgnoreCase {get;set;}
Line Property string Line {get;set;}
LineNumber Property int LineNumber {get;set;}
Matches Property System.Text.RegularExpressions.Match[] Matches {get;set;}
Path Property string Path {get;set;}
Pattern Property string Pattern {get;set;}
Luckily, the property names make sense. Obviously, Pattern is the pattern I specified to find the matches. The LineNumber and Path properties are the file and the line number in the file. So I want the Line property. Here is my revised command:
Select-String -Path C:\fso\myprocesses.txt -Pattern "(iexplore|Handles)" | select line
Here is the command and the revised output. It is quite readable now.
BU, that is all there is to using Select-String. Join me tomorrow when I will talk about more way cool Windows PowerShell stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy