Summary: Microsoft Scripting Guy, Ed Wilson, shows how to use Windows PowerShell to parse XML-formatted Microsoft Exchange Server 2010 audit reports.

Hey, Scripting Guy! Question Hey, Scripting Guy! I have a problem. The search results that return from the New-AdminAuditLogSearch cmdlet are pretty useless. Looking at all that XML in Internet Explorer is not very fun, and the Import-CliXML Windows PowerShell cmdlet is unable to make heads or tails of the XML. I can open it in Microsoft Excel 2010, but the problem is that it seems to create 30 or 40 rows for each record that is returned by the search. Can you help me? Surely, there is an easier way to do this.

—MJ

Hey, Scripting Guy! AnswerHello MJ,

Microsoft Scripting Guy, Ed Wilson, is here. Before I jump into answering your question, I want to put in a plug for International PowerShell User Group Day, which is March 19, 2012. The goal of the International PowerShell User Group Day is to have one global Windows PowerShell user group meeting. This will be a live broadcast from the Arizona PowerShell User Group in Phoenix, Arizona, and the program will include Don Jones and me. (Other speakers are still being lined up.) If you are a Windows PowerShell user group leader, you should consider moving your March meeting to March 19, so your group can dial in and participate in the meeting. I will be speaking from the Charlotte Windows PowerShell User Group meeting in Charlotte, North Carolina, and it will be a lot of fun. If you need to see if there is a Windows PowerShell user group in your area, see the PowerShell Community Groups page.  

MJ, in yesterday’s blog, Use PowerShell to Audit Changes Made to Exchange Server 2010, I talked about using the New-AdminAuditLogSearch cmdlet to run an audit and to email a report that contains the results of the audit query.

Note   I have written several blogs about working with XML from inside Windows PowerShell, and I have also had several great guest bloggers who have also addressed the topic of XML and IT Pros. From a beginner perspective, my blog called Is There an Easier Way to Work with XML Files? is a great place to start.

The XML file that generates from the New-AdminAuditLogSearch cmdlet is a standard formatted file, and it appears in XML Notepad as shown in the image that follows.

Image of XML file

The previous image shows the properties of the first event as follows:

Caller

Cmdlet

Error

ObjectModified

OriginatingServer

RunDate

Succeeded

The two following properties contain not simple strings, but other objects. These two properties show up as additional XmlElements.

CmdletParameters

ModifiedProperties

One thing that is often confusing is that the Import-CliXML cmdlet does not import just any old XML file—it imports only specially formatted XML that generates from the Export-CliXML cmdlet. This is why, your efforts to import via Import-CliXML did not work.

The easiest way to read the contents of the SearchResults.xml file is to use the Get-Content cmdlet to read the contents of the file, and then to cast the type to a System.Xml.XmlDocument type by using the [xml] type accelerator. This is much easier to accomplish than it sounds.

In the following example, the SearchResult.XML file (generated in yesterday’s blog) saved from Outlook, resides in the C:\fso folder. I then use the [XML] type accelerator to convert the text, derived via the Get-Content cmdlet into an XmlDocument.

[xml]$xml = Get-Content C:\fso\SearchResult.xml

When I view the contents of the $xml variable, the searchresults XmlElement appears as illustrated here.

PS C:\> $xml

 

xml                                        SearchResults

---                                        -------------

version="1.0" encoding="utf-8"             SearchResults

To view the objects that are stored in the SearchResults XmlElement, use dotted notation to access the SearchResults property. This technique is shown here.

PS C:\> $xml.SearchResults

 

Event

-----

{Event, Event, Event}

In this example, the SearchResults XmlElement contains three objects, each named Event. To view the objects, use dotted notation to access the Event property as shown here.

$xml.SearchResults.Event

As shown in the image that follows, the Event property contains the audit information that an Exchange administrator seeks.

Image of command output

I can now use standard Windows PowerShell techniques to analyze the data. For example, if I am only interested in the caller and cmdlet that were run during the period of the report, I can use the Select-Object cmdlet as shown here.

PS C:\> $xml.SearchResults.Event | select caller, cmdlet

 

Caller                                     Cmdlet

------                                     ------

iammred.net/Users/Administrator            Enable-Mailbox

iammred.net/Users/Administrator            Enable-Mailbox

iammred.net/Users/Administrator            Enable-Mailbox

I can output to a table by using the Format-Table cmdlet. The following command selects the RunDate, Caller and Cmdlet and outputs to an automatically sized table.

PS C:\> $xml.SearchResults.Event | Format-Table rundate, caller, cmdlet -AutoSize

 

RunDate                   Caller                          Cmdlet

-------                   ------                          ------

2012-01-17T18:04:16-05:00 iammred.net/Users/Administrator Enable-Mailbox

2012-01-17T18:04:09-05:00 iammred.net/Users/Administrator Enable-Mailbox

2012-01-17T18:03:53-05:00 iammred.net/Users/Administrator Enable-Mailbox

The results, stored in the $xml variable are addressable via array index notation. To view the RunDate of the first event, use the [0] notation to retrieve the first element. This technique is shown here.

PS C:\> $xml.SearchResults.Event[0].rundate

2012-01-17T18:04:16-05:00

One really cool way to parse the data is to select the appropriate properties and pipe the results to the Out-GridView cmdlet. It is necessary to use the Select-Object cmdlet to choose the properties because the Out-GridView does not accept a complex object. Therefore, a direct pipeline fails. This technique is shwon here.

$xml.SearchResults.Event | select caller, rundate, cmdlet | Out-GridView

The resulting Grid is shown in the image that follows.

Image of search results

MJ, that is all there is to using Windows PowerShell to parse the XML search results from Exchange Server. Exchange Server Week will continue tomorrow when Microsoft PFE, Norman Drews, talks about using Windows PowerShell to fix annoying NDR mails.

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