{"id":54013,"date":"2009-04-08T23:11:00","date_gmt":"2009-04-08T23:11:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/04\/08\/hey-scripting-guy-how-can-i-check-the-size-of-my-event-log-and-then-backup-and-archive-it-if-it-is-more-than-half-full\/"},"modified":"2009-04-08T23:11:00","modified_gmt":"2009-04-08T23:11:00","slug":"hey-scripting-guy-how-can-i-check-the-size-of-my-event-log-and-then-backup-and-archive-it-if-it-is-more-than-half-full","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-check-the-size-of-my-event-log-and-then-backup-and-archive-it-if-it-is-more-than-half-full\/","title":{"rendered":"Hey, Scripting Guy! How Can I Check the Size of My Event Log and Then Backup and Archive It If It Is More Than Half Full?"},"content":{"rendered":"<p><H2><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> <\/H2>\n<P>Hey, Scripting Guy! We have recently enabled additional security auditing on our network, and I do not want to increase the size of those logs due to the fact that they are already huge. I do not want to turn on circular logging because I need to keep an audit trail for compliance reasons. I need to write a script that I use to check the size of the security event log. If it is more than 50 percent full, I want to backup the log, and then empty the log. I do not know if this is even possible to do via script, but if it were, it would save me several hours of work a week because this is the exact task that I have to do manually every morning and afternoon. <BR><BR>&#8211; DP<\/P><IMG height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> \n<P>Hi DP,<\/P>\n<P>I know what it is like to be chained to a desk all day. If I could write a script to answer all e-mail that is sent to <A href=\"mailto:scripter@microsoft.com\">scripter@microsoft.com<\/A>, it would be cool. Of course, then I would miss out on one of my favorite things to do. I love reading the <B>scripter<\/B> e-mail because I hear from people all over the world who are victims of bad situations. Sometimes, these are due to strange management decisions (such as &#8220;we will not lock down the desktop because it is incompatible with the team concept&#8221;). &#8220;We trust our employees&#8221;\u2014you know what happens then don&#8217;t you? The poor IT pro spends all his or her time fixing stupid mistakes made by clueless users. And as a result that IT pro has no time to spend planning deployments, patching updates, or evaluating new technology. Short of changing jobs what can you do? There are lots of ideas I have come up with over the years, and many of them involve a carefully crafted script such as the one I wrote for you, DP. This one is pretty cool; it looks at the size of the event log. If the event log is more than half full, we backup and archive it.<\/P>\n<TABLE class=\"dataTable\" id=\"E5C\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\">This week is Event Log Week. We have quite a few good scripts that work with event logs in the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/logs\/eventlog\/default.mspx\" target=\"_blank\">Script Center Script Repository<\/A>. The Scripting Guide has some good information about <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/guide\/sas_log_udqz.mspx\" target=\"_blank\">querying event logs<\/A>, <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/guide\/sas_log_hdyb.mspx\" target=\"_blank\">managing event logs<\/A>, and <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/guide\/sas_log_goka.mspx\" target=\"_blank\">writing to event logs<\/A> from a VBScript perspective. These same types of information are covered from a Windows PowerShell perspective in chapter 3 of the <A href=\"http:\/\/www.microsoft.com\/learning\/en\/us\/Books\/9541.aspx\" target=\"_blank\">Windows PowerShell Scripting Guide<\/A>. Over the years, there have been a few \u201cHey, Scripting Guy!\u201d articles on topics such as <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/jan06\/hey0130.mspx\" target=\"_blank\">finding the oldest event in an event log<\/A>, the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/jan06\/hey0131.mspx\" target=\"_blank\">newest event in an event log<\/A>, <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/sept07\/hey0906.mspx\" target=\"_blank\">backing up the event log<\/A> to a text file, <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/sept05\/hey0913.mspx\" target=\"_blank\">retrieving audit failures<\/A> from the event log, or <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/oct04\/hey1026.mspx\" target=\"_blank\">retrieving all failures from the security event log<\/A>. There is also the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/tools\/logparser\/default.mspx\" target=\"_blank\">Log Parser 2.2<\/A>, and we have a number of examples on the Script Center of how to use <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/tools\/logparser\/lpexamples.mspx\" target=\"_blank\">Log Parser<\/A>. The scripts this week are written in <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/msh.mspx\" target=\"_blank\">Windows PowerShell<\/A>. If you need help converting VBScript to Windows PowerShell, you can refer to <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/winpsh\/convert\/default.mspx\" target=\"_blank\">this conversion guide<\/A>.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>We decided to call the script <B>BackUpAndClearEventLog.ps1<\/B>, probably because it backs up and clears an event log (go figure). We do not have this exact script in VBScript version, although here is <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/logs\/eventlog\/lgevvb02.mspx\">a script that clears an event log based upon size<\/A>. The event log portion of the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/logs\/eventlog\/default.mspx\">Script Center Script Repository<\/A> is a nice place to find a good sampling of things you can do with managing event logs. The <B>BackUpAndClearEventLog.ps1<\/B> script is seen here:<\/P><PRE class=\"codeSample\">Param($logName = &#8220;security&#8221;,$backupFolder = &#8220;C:\\backupLogs&#8221;)<\/p>\n<p>Function Get-EventLog([string]$logName)\n{\n $log = Get-WmiObject -Class Win32_NTEventLogFile -filter &#8220;LogFileName = &#8216;$logName'&#8221;\n If($log.MaxFileSize \/ $log.FileSize -ge 50)\n  {\n   &#8220;Log is half full. Backing up now.&#8221;\n   Backup-EventLog($log)\n  } #end if\n Else \n { \n   &#8220;Not backed up: $logName is only &#8221; + ($log.MaxFileSize \/ $log.FileSize).tostring(&#8220;N2&#8243;) +  &#8221; percent full&#8221; \n } #end else\n} #end Get-EventLog<\/p>\n<p>Function Backup-EventLog($log)\n{\n $folder = Join-Path -Path $BackUpFolder -ChildPath (Get-Date).ToString(&#8220;MMddyy_hhmm&#8221;)\n If(-not(Test-Path $folder)) \n   { \n     New-Item -path $folder -itemtype Directory -force | out-Null\n   }\n  $rtn = $log.BackupEventLog(&#8220;$folder\\$logName.evt&#8221;).ReturnValue\n  If($rtn -eq 0)\n    {\n     $log.ClearEventLog() | out-null\n    } #end if\n ELSE \n   {\n    &#8220;$logName could not be cleared. Backup ended with $($rtn)&#8221; \n  }\n} #end Backup-EventLog<\/p>\n<p># *** ENTRY POINT ***\nGet-EventLog -logname $logname\n<\/PRE>\n<P>The first thing that we need to do is to define the command-line parameters that the script will accept. For this script, we wish to accept two input parameters. The first parameter is the name of the log that we will work with. We call this parameter <B>$logname<\/B>. The second parameter we will define is used to specify the path to the backup files. We&#8217;ll call this parameter <B>$backupfolder<\/B>. For each of these parameters, we have also defined default values. These default values will be used if the script is called without any modification. This code is seen here:<\/P><PRE class=\"codeSample\">Param($logName = &#8220;security&#8221;,$backupFolder = &#8220;C:\\backupLogs&#8221;)<\/PRE>\n<P>The first function that we would like to create is called the <B>Get-EventLog<\/B> function and it receives a single input when the function is called. The input that is stored in the variable <B>$logName<\/B> is a string data type. Because of this we use a type constraint to control the type of data that can be passed to the function. As always when we create a function, we must use the <B>function<\/B> keyword as seen&nbsp;here:<\/P><PRE class=\"codeSample\">Function Get-EventLog([string]$logName)\n {\n<\/PRE>\n<P>After we begin the function, we now use the <B>Get-WmiObject<\/B> cmdlet with the class parameter to allow us to access the WMI information that is related to the event log. The WMI class that we need to use is the <B>Win32_NTeventlogfile<\/B> class. Because there are a number of the event log files on the computer we need to use the filter parameter to limit our results to only a specific file. To do this we use the <B>Logfilename<\/B> property and specify the name that we have stored in the <B>$logName<\/B> variable. This is seen here:<\/P><PRE class=\"codeSample\">$log = Get-WmiObject -Class Win32_NTEventLogFile -filter &#8220;LogFileName = &#8216;$logName'&#8221;<\/PRE>\n<P>The Windows event log we are working with is seen in the Event Viewer utility here:<\/P><IMG height=\"360\" alt=\"Image of the Windows event log\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/april\/hey0408\/hsg-04-08-09-1.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>After we have stored the WMI object in the <B>$log<\/B> variable, we use the <B>if<\/B> statement and examine the <B>MaxFileSize<\/B> property. We then divide this property value by the <B>FileSize<\/B> property. If the resulting number is greater than 50, we will proceed to back up the file. This is seen&nbsp;here: <\/P><PRE class=\"codeSample\">If($log.MaxFileSize \/ $log.FileSize -ge 50)\n {\n<\/PRE>\n<P>The first thing that we want to do is to provide a status message to the user. In our example, we use a simple string that states the log is half full and we are backing it up now. After we have displayed this information, we call the <B>Backup-EventLog<\/B> function and pass the WMI object that is contained in the <B>$log<\/B> variable to the function. After we have passed the object to the <B>Backup-EventLog<\/B> function, we end our <B>if<\/B> statement by closing the curly brackets. This is seen&nbsp;here:<\/P><PRE class=\"codeSample\">&#8220;Log is half full. Backing up now.&#8221;\n   Backup-EventLog($log)\n  } #end if\n<\/PRE>\n<P>Now it is time to consider alternative scenarios. If the log is less than half full, we display a status message that states that the log is not backed up. We supply the name of the log and the actual size that is contained in the <B>MaxFileSize<\/B> property of the <B>$log<\/B> object. We then calculate the percentage of the log size in relationship to the maximum file size that the log is permitted to grow. We display a formatted number by using the <B>tostring<\/B> method of the object. Inside the smooth parentheses of the <B>tostring<\/B> method, we use a format specifier from the .NET Framework. The letters used for the format specifier are case sensitive. The capital <B>N<\/B> followed by the number <B>2<\/B> indicates that the number will be displayed with only two numbers trailing the decimal point. This is shown&nbsp;here: <\/P><PRE class=\"codeSample\">Else \n  { \n   &#8220;Not backed up: $logName is only &#8221; + ($log.MaxFileSize \/ $log.FileSize).tostring(&#8220;N2&#8243;) +  &#8221; percent full&#8221; \n  } #end else\n} #end Get-EventLog\n<\/PRE>\n<P>We now need to create the <B>Backup\u2013EventLog<\/B> function. To do this we use the <B>Function<\/B> keyword followed by the name of the function that we will create. The <B>Backup\u2013EventLog<\/B> function will accept a single parameter, which is the object that is stored in the <B>$log<\/B> variablevariable: <\/P><PRE class=\"codeSample\">Function Backup-EventLog($log)\n{\n<\/PRE>\n<P>Next we need to create the path that will be used to hold the backup file. To do this we use the <B>Join-Path<\/B> cmdlet and use the path parameter to specify the parent folder for the backup. The child folder is created based upon the date. To create the name for the child folder we use the <B>Get\u2013Date<\/B> cmdlet and feed the <B>date time<\/B> object to the <B>tostring<\/B> method. Inside the parentheses of the <B>tostring<\/B> method, we once again use a .NET Framework format specifier. The capital <B>M<\/B> is used to indicate the month, the lowercase <B>d<\/B> is used for the day, and the lowercase <B>y<\/B> indicates the year. The lowercase <B>h<\/B> is the hour and the lowercase <B>m<\/B> stands for the minutes. Because two letters are used in the pattern, it indicates that two numbers will be represented. This is seen here:<\/P><PRE class=\"codeSample\">$folder = Join-Path -Path $BackUpFolder -ChildPath (Get-Date).ToString(&#8220;MMddyy_hhmm&#8221;)<\/PRE>\n<P>If the folder does not exist, we create it. We use the <B>Test-Path<\/B> cmdlet to see if the folder exists. If the folder does not exist, we use the <B>New-Item<\/B> cmdlet to create the new folder. Because we do not want to see the feedback from the command, we pipeline the output to the <B>Out-Null<\/B> cmdlet:<\/P><PRE class=\"codeSample\">If(-not(Test-Path $folder)) \n   { \n     New-Item -path $folder -itemtype Directory -force | out-Null\n   }\n<\/PRE>\n<P>The <B>BackupEventLog<\/B> method is used to (shocking, we know) back up the event log. The method receives the path as well as the file name and extension for the backup file. When the method is called, it returns an object that indicates the status of the method call. We&#8217;re interested in a return code of zero, which means there were no errors. We store the return code in the <B>$rtn<\/B> variable: <\/P><PRE class=\"codeSample\">$rtn = $log.BackupEventLog(&#8220;$folder\\$logName.evt&#8221;).ReturnValue<\/PRE>\n<P>After the destination folder has been created and the event log backed up, the directory structure looks similar to the one seen here:<\/P><IMG height=\"326\" alt=\"Image of the directory structure\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/april\/hey0408\/hsg-04-08-09-2.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>If the <B>$rtn<\/B> variable is equal to zero, we empty the event log by using the <B>ClearEventLog<\/B> method. There are no parameters for this method, so the parentheses used for the method are empty. The <B>ClearEventLog<\/B> method does return an error code; however, we are not interested in this, so we pipeline it to the <B>Out-Null<\/B> cmdlet. This is seen&nbsp;here: <\/P><PRE class=\"codeSample\">If($rtn -eq 0)\n    {\n     $log.ClearEventLog() | out-null\n    } #end if\n<\/PRE>\n<P>If the backup was not successful, the value contained in the <B>$rtn<\/B> variable will not be equal to zero. If this is the case, we do not clear the event log, so we must print a message to this effect: <\/P><PRE class=\"codeSample\">ELSE \n   {\n    &#8220;$logName could not be cleared. Backup ended with $($rtn)&#8221; \n  }\n} #end Backup-EventLog\n<\/PRE>\n<P>We are now at the entry point to the script. Everything we have seen so far is a lot of preparatory work. The script executes by calling the <B>Get-EventLog<\/B> function and passing the log name, which is contained in the <B>$logname<\/B> variable. This is seen here:<\/P><PRE class=\"codeSample\">Get-EventLog -logname $logname<\/PRE>\n<P>Well, DP, we have created a script that looks at the size of an event log, and if the log is more than half full, it backs up the log and then empties it. It was a fun and interesting scenario. Join us tomorrow as we continue with Event Log week. Until then, take care. <\/P>\n<P>&nbsp;<\/P>\n<P><B>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/B><\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! We have recently enabled additional security auditing on our network, and I do not want to increase the size of those logs due to the fact that they are already huge. I do not want to turn on circular logging because I need to keep an audit trail for compliance reasons. I [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[97,98,3,45],"class_list":["post-54013","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-event-logs","tag-logs-and-monitoring","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! We have recently enabled additional security auditing on our network, and I do not want to increase the size of those logs due to the fact that they are already huge. I do not want to turn on circular logging because I need to keep an audit trail for compliance reasons. I [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54013","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\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=54013"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54013\/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=54013"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=54013"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=54013"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}