Contact

Subscribe via Email

Subscribe via RSS/JSON

Categories

Recent Posts

Creative Commons Attribution 4.0 International License
© Rakhesh Sasidharan

Elsewhere

The difference between help and get-help

I always assumed help was just an alias for the Get-Help cmdlet. After all if you type

you get the help page for Get-Help.

But there is a difference. Using help seems to pipe the output through more as you get a page by page display, whereas using Get-Help dumps everything at one go. I checked the aliases though but no alias for help could be found either.

Turns out help is a function! The best way to find out what a command is, is to use the Get-Command cmdlet. Like thus:

And to view what the function is, pipe the output through format-list (or select and expand the Definition property):

And here you can see the help function actually calls the Get-Help cmdlet and helpfully pipes the output through more for you. Also, the function is set to use the help page for Get-Help which explains the help page anomaly.

Get-Member quirk

I am sure I mentioned this before (I read it in a blog post somewhere and has usually served me well): Get-Member has a quirk when it comes to arrays in that if you pipe it an array it will give you the members of the elements of the array, not the members of the array itself.

To get the members of the array itself, use the -InputObject parameter:

Use PowerShell to get the names and email addresses of members of a distribution group

There are easier ways probably but this is what I use:

Using Get-WinEvent to look at Windows event logs

Playing around with Get-WinEvent today. I find it very useful, especially when dealing with remote computers (as I have to at work). Launching Event Viewer, connecting to a remote computer (or even local computer), and then sifting through logs (or creating filters to sift) seems very cumbersome when I can acheive the same results much faster via PowerShell.

As you might have seen the Event Viewer has various logs. Using Get-WinEvent you can select which logs to focus on. To get a list of available logs do the following:

Probably better to filter through format-table for neater output:

To view details of a specific log, replace * with the name (and pipe output to format-list to view all the details):

To view all events in a log do the following:

There’s a lot of output, so good to restrict the number of entries:

Strangely there’s no easy way to restrict the entries starting at a certain time. There is, but no easy switchy way. Instead you have to do the following:

We use the -FilterHashTable switch here. This takes a hash table containing the log name as well as other parameters to filter on (you can start time, end time, provider name, ID, etc, and can combine multiple parameters). In the example above I want all events from the “System” log for the last 2 hours – so I use the get-date cmdlet, use it’s method AddHours() and set the number of hours to be added as -2.

In the next example I filter all events from the “System” log with event ID 7036 starting from now yesterday up to an hour ago.

To change the displayed order of events from newest-first to oldest-first use the -Oldest switch.

Beats piping the output to a sort cmdlet to reverse-sort!

Similar to how you can list the lognames you can list providers too:

This gives a list of the providers (the applications or sources that log events) and the logs to which they send events. The list can be huge, so a good idea is to pipe the output through where-object to filter by the providers you are interested in:

Note: The case doesn’t really matter above (“PowerShell”) because the -match operator is case in-sensitive by default. Use -cmatch if you care about case.

Back to the -FormatHashTable switch: this one takes a “ProviderName” key too containing the name of the provider you wish to filter on. The name can contain wildcards if you want to search multiple providers. For instance, the example below searches the “Application” log for all entries by the Citrix providers (there are many hence the wildcard) logged in the past three hours:

Note: In the example above, I can omit the logname. The hashtable requires either the log name or the provider name (or the path to a log). If you don’t care about the log name or provider name, mention one of these but leave the value as a wildcard. Like thus:

The above example gets all logs from the past 3 hours.

The default output of Get-WinEvent includes a lot of fields. Best to use format-table or select-object to only show what you want. In the example below I use select-object to select just the Message, ID, and TimeCreated properties. Further I pipe the output to a CSV file (doing that just to show how easy it is to quickly pull some remote logs into a CSV file):

Taking PowerShell on a date

I needed to filter the event logs from a remote computer for power off events. The user was powering it off himself every now and then, but wouldn’t believe me when I said so. No problem, thanks to the event logs all his shutdown requests are logged so it’s only a matter of culling it out.

I could have user Event Viewer but PowerShell is way easier. I only need to check the System event logs for any events with ID 1074. Further, for every shutdown, events with this ID are logged twice – one starting with the line “The process C:Windowssystem32winlogon.exe …” the other starting with the line “The process Explorer.EXE has initiated the power off …” – so I’d like to filter the output to just include one of these lines. Finally, I’d also like the day of the week to be shown.

So here’s what I did:

So far so good. I use Get-WinEvent to return the event logs I want, use the Message property of these returned objects to filter logs containing just the text we want. And finally I use the TimeCreated property of these objects to display the time and day. This TimeCreated property is the subject of this post so let’s focus on that further.

First, how do we get the members and properties of the objects returned by Get-WinEvent? Here’s how:

Notice the TimeCreated property.

The TimeCreated property is an object of class DateTime. To get the day of the date instance, use the TimeCreated.DayofWeek property. Which is what I extract via the Format-Table expression in my initial code:

This post from the “Hey, Scripting Guy! Blog” is a good read on Get-WinEvent and the DateTime class.

Focussing on the DateTime class, this is the type of the object returned by the get-date cmdlet too. Although not obvious from the syntax of the get-date cmdlet, you can use it to return a DateTime object instance of the date you specify as string. Like thus:

What’s more, you can even format the string:

The -Format switch takes a format specifier. As seen above “dd” stands for the date, “ddd” stands for the day in short-hand, “dddd” stands for the date in longhand, and so on.

You can also typecast a string to the DateTime class:

The typecast technique has a limitation though in that it expects the input to be in the format of US, i.e. “MM/dd/YYYY”. The DateTime class has a static member called Parse(), however, that is smart enough the use the country/ culture of the computer.

How do we parse the date if it’s in a different format though? Both the get-date cmdlet and the [datetime]::Parse() method fail if the input string does not match the date format of the computer:

It is possible to specify the date format of the input string. This only works with the Parse() method though. Like thus (thanks to this blog post):

The Globalization.cultureinfo class has a GetCultureInfo() method, so what we are doing above is we create a variable that is an instance of the “en-US” culture and then pass this variable to the Parse() method so it knows which format to parse the input in. Of course we could have also specified the whole thing on one line:

Let’s examine the Globalization.cultureinfo class. First, let’s examine its static members and properties:

The GetCulture() method can be used to list all available cultures:

To get details about a specific culture use the GetCultureInfo() method:

The LCID corresponds to the Locale ID assigned by Microsoft. To see all the properties use the get-member cmdlet or format-list to see the values:

On the topic of dates, the DateTimeFormat property seems interesting:

Notice the ShortDatePattern above. This is exactly what the -Format switch of Get-Date cmdlet expects, so one can use this to format the output of Get-Date in a different locale. Like thus:

So now we have seen to use the [datetime]::Parse() method to parse an input string into a DateTime object while specifying the country format of the input string. We have also seen how to output the result of get-date in the format of a different country. Both methods use the [Globalization.cultureinfo] class.

Lastly, there is an easy way to parse any string – irrespective of whether it matches the format of a country or not – into a DateTime object via the ParseExact() method. This is worth mentioning as without such a method one would have to resort to regular expressions and such!

In the example below we match an input string with time “02:50PM” by specifying the format as “hh:mmtt” to the ParseExact() method.

I am not sure what the third parameter of this method is supposed to be. Most examples put it as $null. It seems to take a “culture” as input, but I am not sure how it affects the output. Instead of $null the following too seem to work: $(get-culture), [Globalization.Cultureinfo]::GetCultureInfo("en-US") (“en-GB” too works), and [Globalization.Cultureinfo]::InvariantCulture.

The format can contain other text too. Escape the characters of such text with a slash or put the text within quotes ':

And just to show what happens if the format does not match:

Thanks to these two posts for showing me ParseExact().