Troubleshoot Outlook Problems with PowerShell

Summary: Microsoft Scripting Guy Ed Wilson teaches how to use Windows PowerShell to troubleshoot Microsoft Outlook problems.


Hey, Scripting Guy! QuestionHey, Scripting Guy! I have a problem with Microsoft Outlook on my laptop. It seems that it goes to sleep or something. I will be working, go to check my email, and nothing appears. But if I look at my Windows 7 mobile phone, it shows that new email is in my inbox. I am thinking that I have a problem with Outlook.



Hey, Scripting Guy! AnswerHello BT,

Microsoft Scripting Guy Ed Wilson here. The Scripting Wife and I had a wonderful time at the Geek Ready conference. She knows many of the Microsoft premier field engineers (PFEs) because she has met them at various Windows PowerShell User group meetings, at conferences, or just from hanging around me. She had a chance to meet several PFEs who have written guest Hey, Scripting Guy! Blog articles, but that she had never met in person. It really was awesome. We were up late on several nights having “Windows PowerShell side meetings” with various PFEs, and on a couple occasions, we ended up having impromptu script club meetings. The results of all this engagement will be appearing for months to come on the Hey, Scripting Guy! Blog, so stay tuned.

Anyway, with all the geeks taking over the hotel where we were staying, poor Microsoft Outlook was struggling. In fact, Internet connectivity was spotty most of the time, just due to the sheer magnitude of the demands placed on the infrastructure by us. The nice thing is that, by using Windows PowerShell, I can do an awful lot of discovery.

When I am doing event log exploration, things go a whole lot faster if I store the particular lot in a variable. So that is what I am going to. Microsoft Outlook writes events to the application log using the source id of outlook. I therefore use the Get-EventLog cmdlet and gather up all the entries that have a source of outlook. I store these EventLogEntry objects in a variable I call $log. The EventLogEntry .NET Framework class appears in the System.Diagnostics namespace, and documentation appears on MSDN. This command is shown here:

$log = Get-EventLog application -Source outlook

Once I have all of the outlook entries in a variable, I can begin to examine them. I am curious about how many entries I have, so I use the count property to see. This command and output are shown here:

PS C:\> $log = Get-EventLog application -Source outlook

PS C:\> $log.count


Next, I want to see what type of structure I am dealing with, so I index into the array of records, and pick off one record to examine and pipe the results to the Format-List cmdlet (fl is an alias for the Format-List cmdlet). Here is the command I use:

$log[0] | fl * -Force

This command and the associated output appear in the following figure.

Image of command and associated output

Wow, as it turns out, that was a bad example because it goes on and on and on. It can be useful, however, because this shows me all of the add-ins that Microsoft loads. Remember, seeing the Microsoft Outlook splash screen that shows how many add-ins it is loading? It looks like EventID 45 tells me about loading add-ins.

A better event log entry is the one that is shown in the following figure. The reason this event log entry is better is that it allows me to see representative data from all of the different properties in a single screen shot.

Image of better event log entry

Event ID 26 looks like it tells me when Microsoft Outlook has lost connectivity to the Microsoft Exchange server. Hmmm, that might be useful. Let me look at all event ID 26s and see what they say. To do this, I pipe the collection of event log entries that are stored in the $log variable to the Where-Object cmdlet (? Is an alias for Where-Object). In the script block associated with the Where-Object cmdlet, I look for eventid that is equal (-eq) to 26. This command is shown here:

$log | ? {$_.eventid -eq 26}

My screen quickly floods with entries. Interestingly enough, it seems that Event ID 26 reports lost connectivity as well as restored connectivity. This can actually be a useful thing. What I can do first is look at how many disconnects and how many connection restored messages there are. This command is shown here:

PS C:\> $log | ? {$_.eventid -eq 26} | group message -NoElement | select name, count | ft -AutoSize

Name                                                                                               Count

—-                                                                                               —–

Connection to Microsoft Exchange has been lost. Outlook will restore the connection when possible.    36

Connection to Microsoft Exchange has been restored.                                                   34

Now that I see that there are a significant number of times when the connection to the Microsoft Exchange server dropped, I would really like to see when this is happening. To do this, I want to focus on the timewritten property from the eventlog. The problem is that if I find my events, and group by the timewritten property, the result will be 70 separate lines and no real grouping because each timewritten record will be unique. Therefore, nothing exists to group on. The command is shown here:

$log | ? {$_.eventid -eq 26} | group timewritten

The command and output are shown in the following figure.

Image of command and output

The trick is to realize that the timewritten property contains a DateTime object. This is important because I know that an instance of the DateTime object exposes a day property. I can then use the Group-Object cmdlet to organize the eventlog records by day. I used the Get-Member cmdlet (gm is an alias) to discover that the timegenerated property contains a DateTime object. This command and output are shown here:

PS C:\> $log[0] | gm timegenerated

   TypeName: System.Diagnostics.EventLogEntry#application/Outlook/1073741869


Name          MemberType Definition

—-          ———- ———-

TimeGenerated Property   System.DateTime TimeGenerated {get;}


The problem is exposing that DateTime object to the Group-Object cmdlet. For example, the following command attempts to use dotted notation to directly access the day property of the DateTime object:

$log | ? {$_.eventid -eq 26} | group

The command and output are shown here (they are not impressive):

PS C:\> $log | ? {$_.eventid -eq 26} | group

Count Name                      Group

—– —-                      —–

   70                           {System.Diagnostics.EventLogEntry, System.Diagnostics.EventLogEntry,

The following commands also do not work. In fact, some generate errors:

$log | ? {$_.eventid -eq 26} | group (timewritten).day

$log | ? {$_.eventid -eq 26} | group $(timewritten).day

$log | ? {$_.eventid -eq 26} | group $

The trick is to use the Select-Object cmdlet with the expandproperty parameter to expand the timewritten property from the Get-EventLog. In this way, I can then use the Group-Object cmdlet to group the eventlog records by day. I decided to leave the details because they let me see which days I am having problems. The command is shown here:

$log | ? {$_.eventid -eq 26} | select -expandproperty timewritten | group day

The command and associated output are shown in the following figure.

Image of command and associated output

It is obvious from the preceding figure, that there were problems on November 4 and October 16. This is great information because I could work with a customer, or someone who says, “I had a problem with Outlook last week sometime. I don’t really remember when, but it seemed like it kept dropping off, and not working.” And with Windows PowerShell and the Get-EventLog cmdlet, I can actually connect remotely to their computer and retrieve the information I need. And then I can say, “Yes, I see you had a problem on November 4, but we were applying patches to the Exchange server that day, and it was up and down all day. So, no, there is no problem with Outlook.”

But what if we look back, and we were not performing maintenance? Maybe, instead I want to see if there is a pattern by hour. I also know that the DateTime object contains an hour property. Therefore, using my trick from earlier, I come up with the following command:

$log | ? {$_.eventid -eq 26} | select -expandproperty timewritten | group hour

The command and associated output follow. It is very revealing. Thirty-six of the disconnects occurred between the hours of 20:00 (8:00 P.M.) and 22:00 (10:00 P.M.).

Image of command and associated output showing disconnects


BT, that is all there is to using Windows PowerShell to assist in troubleshooting Microsoft Outlook problems. Join me tomorrow for more cool Windows PowerShell things.  

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy



Comments (7)

  1. Anonymous says:

    Thanks for these trick !

  2. Anonymous says:


    Sorry for the typo.

  3. Anonymous says:

    Dear Ed!

    Your last attempt to use grouping directly on log entries…:

    $log | ? {$_.eventid -eq 26} | group $

    … was pretty close, it missed only something around the code on which data should be grouped:

    $log | ? {$_.eventid -eq 26} | group { $ }

    But I would probably choose different grouping code:

    $log | ? { $_.eventId -eq 26 } | group { $_.TimeWritten.ToShortDateString() }

    Done. 😉

  4. Klaus Schulte says:

    Hi Ed,

    thank you for reminding me of the Get-Eventlog Cmdlet!

    I nearly forgot about it since the last scripting games …

    Analyzing the event logs of our client PCs is really easy with powershell!

    That's something where having PS at our fingertips rocks!

    The one liner "$log = Get-EventLog application -Source outlook -computername RemoteComputer"

    is a highlight on its own!

    Up to the advent of powershell I would have (if you don't have high level management infrastructure systems … or you are no admin, like me) opened a remote desktop connection to "RemoteComputer", clicked through the start menu entries until we see the event log icon.

    Double clicking it might take a while until the list of events expands and even then we have to filter or at least sort the events and scroll to the potentially interesting part of the list.

    But you still will have to copy and paste some of the entries from the list if you have to analyze problems further. At this point we have TEXT … NO OBJECTS! So the nice things presented here like grouping, sorting, filtering … on special properties of these log entries has been impossible or at least much more difficult.

    The biggest deal might be (Having enabled remoting on our remote machines) that we can collect data from each of our departments workstations in a powershell one liner! We can save the results to a file and analyze them offline at any time to produce reports of the most common problems related to all or selected machines ( and maybe we like to produce beautiful excel reports directly from our  powershell console … 🙂

    That's good news … isn't it?


  5. Ed Wilson says:

    @Klaus Schulte don't forget too much from last years Scripting Games, because the 2012 Scripting Games are coming in April … only a few months away. Yes, I always like using the Get-EventLog cmdlet. It is very easy to use, and very powerful. I am amazed by the things I find out in the log files. I was really happy when I figured out I could group the entries by the time they were written.

  6. Ed Wilson says:

    @Bartek Bielawski Hello my friend! You are right about using a script block to force evaluation of the DateTime object to permit grouping by day and by hour. The difference, is that in my method of using Select -ExpandProperty is that in the element information, I now have the actual timestamps. Also when grouping by timewritten to string, unelss there are a whole bunch of date / times that are exactly the same time, then the grouping will only be groups of 1. In addition, once you call tostring, you no longer have a datetime object … you have a string. All this aside, you are absolutely correct, if I had of added curly brackets around the timewritten property it would have forced it would have opened it up, and allowed me to meet my original goal. Thank you very much for sharing this … it is a great trick to remember!