{"id":11361,"date":"2012-01-26T00:01:00","date_gmt":"2012-01-26T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2012\/01\/26\/use-powershell-to-parse-xml-exchange-audit-results\/"},"modified":"2012-01-26T00:01:00","modified_gmt":"2012-01-26T00:01:00","slug":"use-powershell-to-parse-xml-exchange-audit-results","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/use-powershell-to-parse-xml-exchange-audit-results\/","title":{"rendered":"Use PowerShell to Parse XML Exchange Audit Results"},"content":{"rendered":"<p><b>Summary<\/b>: Microsoft Scripting Guy, Ed Wilson, shows how to use Windows PowerShell to parse XML-formatted Microsoft Exchange Server 2010 audit reports.<\/p>\n<p><span><span><span><span><span><span><span><span><img decoding=\"async\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\" \/><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>&nbsp;Hey, Scripting Guy! I have a problem. The search results that return from the <b>New-AdminAuditLogSearch<\/b> cmdlet are pretty useless. Looking at all that XML in Internet Explorer is not very fun, and the <b>Import-CliXML <\/b>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.<\/p>\n<p>&mdash;MJ<\/p>\n<p><span><span><span><span><span><span><span><span><img decoding=\"async\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\" \/><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span>Hello MJ,<\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. Before I jump into answering your question, I want to put in a plug for <a href=\"http:\/\/ipugd.org\/\" target=\"_blank\">International PowerShell User Group Day<\/a>, 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 <a href=\"http:\/\/powershellgroup.org\/charlotte.nc\" target=\"_blank\">Charlotte Windows PowerShell User Group<\/a> 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 <a href=\"http:\/\/powershellgroup.org\/\" target=\"_blank\">PowerShell Community Groups page<\/a>. &nbsp;<\/p>\n<p>MJ, in yesterday&rsquo;s blog, <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2012\/01\/25\/use-powershell-to-audit-changes-made-to-exchange-server-2010.aspx\" target=\"_blank\">Use PowerShell to Audit Changes Made to Exchange Server&nbsp;2010<\/a>, I talked about using the <b>New-AdminAuditLogSearch <\/b>cmdlet to run an audit and to email a report that contains the results of the audit query.<\/p>\n<p><b>Note<\/b>&nbsp;&nbsp;&nbsp;I have written <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/tags\/windows+powershell\/xml\/guest+blogger\/\" target=\"_blank\">several blogs about working with XML<\/a> from inside Windows PowerShell, and I have also had several great guest bloggers who have also addressed the topic of <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/tags\/windows+powershell\/xml\/guest+blogger\/\" target=\"_blank\">XML and IT Pros<\/a>. From a beginner perspective, my blog called <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2009\/11\/16\/hey-scripting-guy-november-16-2009.aspx\" target=\"_blank\">Is There an Easier Way to Work with XML Files?<\/a> is a great place to start.<\/p>\n<p>The XML file that generates from the <b>New-AdminAuditLogSearch<\/b> cmdlet is a standard formatted file, and it appears in <a href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?familyid=72d6aa49-787d-4118-ba5f-4f30fe913628&amp;displaylang=en\" target=\"_blank\">XML Notepad<\/a> as shown in the image that follows.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1325.HSG-1-26-12-01.jpg\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1325.HSG-1-26-12-01.jpg\" alt=\"Image of XML file\" title=\"Image of XML file\" \/><\/a><\/p>\n<p>The previous image shows the properties of the first event as follows:<\/p>\n<p style=\"padding-left: 30px\">Caller<\/p>\n<p style=\"padding-left: 30px\">Cmdlet<\/p>\n<p style=\"padding-left: 30px\">Error<\/p>\n<p style=\"padding-left: 30px\">ObjectModified<\/p>\n<p style=\"padding-left: 30px\">OriginatingServer<\/p>\n<p style=\"padding-left: 30px\">RunDate<\/p>\n<p style=\"padding-left: 30px\">Succeeded<\/p>\n<p>The two following properties contain not simple strings, but other objects. These two properties show up as additional XmlElements.<\/p>\n<p style=\"padding-left: 30px\">CmdletParameters<\/p>\n<p style=\"padding-left: 30px\">ModifiedProperties<\/p>\n<p>One thing that is often confusing is that the <b>Import-CliXML <\/b>cmdlet does not import just any old XML file&mdash;it imports only specially formatted XML that generates from the <b>Export-CliXML <\/b>cmdlet. This is why, your efforts to import via <b>Import-CliXML <\/b>did not work.<i><\/i><\/p>\n<p>The easiest way to read the contents of the SearchResults.xml file is to use the <b>Get-Content <\/b>cmdlet to read the contents of the file, and then to cast the type to a <i>System.Xml.XmlDocument <\/i>type by using the [xml] type accelerator. This is much easier to accomplish than it sounds.<\/p>\n<p>In the following example, the SearchResult.XML file (generated in yesterday&rsquo;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 <b>Get-Content <\/b>cmdlet into an <i>XmlDocument.<\/i><\/p>\n<p style=\"padding-left: 30px\">[xml]$xml = Get-Content C:\\fso\\SearchResult.xml<\/p>\n<p>When I view the contents of the $xml variable, the <i>searchresults <\/i>XmlElement<i> <\/i>appears as illustrated here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $xml<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">xml&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SearchResults<\/p>\n<p style=\"padding-left: 30px\">&#8212;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8212;&#8212;&#8212;&#8212;-<\/p>\n<p style=\"padding-left: 30px\">version=&#8221;1.0&#8243; encoding=&#8221;utf-8&#8243;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SearchResults<\/p>\n<p>To view the objects that are stored in the <i>SearchResults <\/i>XmlElement, use dotted notation to access the <b>SearchResults<\/b><i> <\/i>property. This technique is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $xml.SearchResults<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">Event<\/p>\n<p style=\"padding-left: 30px\">&#8212;&#8211;<\/p>\n<p style=\"padding-left: 30px\">{Event, Event, Event}<\/p>\n<p>In this example, the <i>SearchResults <\/i>XmlElement contains three objects, each named Event<i>. <\/i>To view the objects, use dotted notation to access the <b>Event<\/b> property as shown here.<\/p>\n<p style=\"padding-left: 30px\">$xml.SearchResults.Event<\/p>\n<p>As shown in the image that follows, the <b>Event<\/b> property contains the audit information that an Exchange administrator seeks.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7382.HSG-1-26-12-02.jpg\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7382.HSG-1-26-12-02.jpg\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>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 <b>Select-Object <\/b>cmdlet as shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $xml.SearchResults.Event | select caller, cmdlet<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">Caller&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cmdlet<\/p>\n<p style=\"padding-left: 30px\">&#8212;&#8212;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8212;<\/p>\n<p style=\"padding-left: 30px\">iammred.net\/Users\/Administrator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Enable-Mailbox<\/p>\n<p style=\"padding-left: 30px\">iammred.net\/Users\/Administrator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Enable-Mailbox<\/p>\n<p style=\"padding-left: 30px\">iammred.net\/Users\/Administrator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Enable-Mailbox<\/p>\n<p>I can output to a table by using the <b>Format-Table <\/b>cmdlet. The following command selects the <b>RunDate<\/b><i>, <\/i><b>Caller<\/b><i> <\/i>and <b>Cmdlet<\/b><i> <\/i>and outputs to an automatically sized table.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $xml.SearchResults.Event | Format-Table rundate, caller, cmdlet -AutoSize<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">RunDate&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Caller&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cmdlet<\/p>\n<p style=\"padding-left: 30px\">&#8212;&#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8212;&#8212;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8212;<\/p>\n<p style=\"padding-left: 30px\">2012-01-17T18:04:16-05:00 iammred.net\/Users\/Administrator Enable-Mailbox<\/p>\n<p style=\"padding-left: 30px\">2012-01-17T18:04:09-05:00 iammred.net\/Users\/Administrator Enable-Mailbox<\/p>\n<p style=\"padding-left: 30px\">2012-01-17T18:03:53-05:00 iammred.net\/Users\/Administrator Enable-Mailbox<\/p>\n<p>The results, stored in the $<b>xml<\/b> variable are addressable via array index notation. To view the <b>RunDate<\/b> of the first event, use the [0] notation to retrieve the first element. This technique is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $xml.SearchResults.Event[0].rundate<\/p>\n<p style=\"padding-left: 30px\">2012-01-17T18:04:16-05:00<\/p>\n<p>One really cool way to parse the data is to select the appropriate properties and pipe the results to the <b>Out-GridView <\/b>cmdlet. It is necessary to use the <b>Select-Object <\/b>cmdlet to choose the properties because the <b>Out-GridView <\/b>does not accept a complex object. Therefore, a direct pipeline fails. This technique is shwon here.<\/p>\n<p style=\"padding-left: 60px\">$xml.SearchResults.Event | select caller, rundate, cmdlet | Out-GridView<\/p>\n<p>The resulting Grid is shown in the image that follows.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2656.HSG-1-26-12-03.jpg\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2656.HSG-1-26-12-03.jpg\" alt=\"Image of search results\" title=\"Image of search results\" \/><\/a><\/p>\n<p>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.<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, shows how to use Windows PowerShell to parse XML-formatted Microsoft Exchange Server 2010 audit reports. &nbsp;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 [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[28,180,3,4,45,165],"class_list":["post-11361","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-messaging-and-communication","tag-microsoft-exchange-2010","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell","tag-xml"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, shows how to use Windows PowerShell to parse XML-formatted Microsoft Exchange Server 2010 audit reports. &nbsp;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 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/11361","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=11361"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/11361\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=11361"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=11361"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=11361"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}