Skip to content

Exchange: Cleanup of the Exchange Logs with PowerShell

I prepared a new Exchange Environment for a migration project. But after all the tests the logs has grown and I want to start fresh.

Here is a quick and dirty way to remove all Exchange (and IIS) related Logs on and Exchange Server:

#requires -Version 3.0 -RunAsAdministrator
<#
      .SYNOPSIS
      Cleanup some of the Exchange Logs

      .DESCRIPTION
      Cleanup some of the Exchange Logs

      .EXAMPLE
      PS C:\> .\Clear-LogFileDirectory.ps1

      .NOTES
      Wrapper for the Clear-LogFileDirectory function
      Everaything is hardcoded for this wrapper ;-)

      .LINK
      Clear-LogFileDirectory
#>
[CmdletBinding(ConfirmImpact = 'None')]
param ()

# Files older then 1 day are deleted
$Days = 1

# Exchange Base Directory
$ExchangeBaseDir = 'D:\Exchange Server'

# Exchaneg Version (Directory)
$ExchangeVersion = 'V15'

# Where to find the IIS stuff
$IISBaseDir = "$env:HOMEDRIVE\inetpub"


#region IIS
# Append the Log Stuff for the Call below
$IISLogPath = $IISBaseDir + '\logs\LogFiles\'
#endregion IIS

#region Exchange
# Combine the values
$ExchangeDirectoryPath = $ExchangeBaseDir + '\' + $ExchangeVersion

# Append the Log Stuff for the Call below
$ExchangeLoggingPath = $ExchangeDirectoryPath + '\Logging\'
$ExchangeETLTraces = $ExchangeDirectoryPath + '\Bin\Search\Ceres\Diagnostics\ETLTraces\'
$ExchangeETLLogs = $ExchangeDirectoryPath + '\Bin\Search\Ceres\Diagnostics\Logs'
#endregion Exchange

#region HelperFunction
function Clear-LogFileDirectory
{
   <#
         .SYNOPSIS
         Cleanup Files in a given Directory

         .DESCRIPTION
         Cleanup Files in a given Directory

         .PARAMETER Path
         Specifies a path, multivalue or wildcards are not yet supported!
         No default so far!

         .PARAMETER Days
         Age of the Files to Delete.
         Default is 7

         .EXAMPLE
         PS C:\> Clear-LogFileDirectory -Path "c:\inetpub\logs\LogFiles\"

         .NOTES
         Mind the Gap:
         Everything within the given directory will be deleted, without any further interaction!
   #>

   [CmdletBinding(ConfirmImpact = 'Low',
   SupportsShouldProcess)]
   param
   (
      [Parameter(Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName,
      HelpMessage = 'Specifies a path, multivalue or wildcards are not yet supported!')]
      [ValidateNotNullOrEmpty()]
      [Alias('Folder', 'TargetFolder')]
      [string]
      $Path,
      [Parameter(ValueFromPipeline,
      ValueFromPipelineByPropertyName)]
      [ValidateNotNullOrEmpty()]
      [Alias('Age', 'FileAge')]
      [int]
      $Days = 7
   )

   begin
   {
      #region Defaults
      $CNT = 'Continue'
      $SCT = 'SilentlyContinue'
      #endregion Defaults

      Write-Verbose -Message ('START: Processing of {0}' -f $Path)
   }

   process
   {
      if (Test-Path -Path $Path -ErrorAction $SCT)
      {
         $Now = (Get-Date)
         $LastWrite = $Now.AddDays(-$Days)

         #region FindAndFilterFiles
         # Splat the Parameters
         $paramFindAndFilterFiles = @{
            Path        = $Path
            Recurse     = $true
            ErrorAction = $SCT
         }
         $Files = (Get-ChildItem @paramFindAndFilterFiles | Where-Object -FilterScript {
               ($_.Name -like '*.log') -or ($_.Name -like '*.blg') -or ($_.Name -like '*.etl')
            } | Where-Object -FilterScript {
               $_.lastWriteTime -le $LastWrite
         } | Select-Object -ExpandProperty FullName)
         #endregion FindAndFilterFiles

         #region FileLooper
         foreach ($File in $Files)
         {
            Write-Verbose -Message ('Deleting file {0}' -f $File)
            try
            {
               if ($pscmdlet.ShouldProcess($File, 'Delete'))
               {
                  #region DeleteFilesFound
                  # Splat the Parameters
                  $paramDeleteFilesFound = @{
                     Path        = $File
                     Force       = $true
                     Confirm     = $false
                     ErrorAction = 'Stop'
                  }
                  $null = (Remove-Item @paramDeleteFilesFound)
                  #endregion DeleteFilesFound
               }
            }
            catch
            {
               #region ErrorHandler
               # get error record
               [Management.Automation.ErrorRecord]$e = $_

               # retrieve information about runtime error
               $info = [PSCustomObject]@{
                  Exception = $e.Exception.Message
                  Reason    = $e.CategoryInfo.Reason
                  Target    = $e.CategoryInfo.TargetName
                  Script    = $e.InvocationInfo.ScriptName
                  Line      = $e.InvocationInfo.ScriptLineNumber
                  Column    = $e.InvocationInfo.OffsetInLine
               }

               $info | Out-String | Write-Verbose

               Write-Warning -Message ($info.Exception) -ErrorAction $CNT -WarningAction $CNT
               #endregion ErrorHandler
            }
         }
         #endregion FileLooper
      }
      else
      {
         Write-Error -Message ("The folder {0} doesn't exist! Check the folder path!" -f $Path)
      }
   }

   end
   {
      Write-Verbose -Message ('DONE: Processed {0}' -f $Path)
   }
}
#endregion HelperFunction

#region FunctionWrapper
Clear-LogFileDirectory -Path $IISLogPath -Days $Days
Clear-LogFileDirectory -Path $ExchangeLoggingPath -Days $Days
Clear-LogFileDirectory -Path $ExchangeETLTraces -Days $Days
Clear-LogFileDirectory -Path $ExchangeETLLogs -Days $Days
#endregion FunctionWrapper

It is also part of my PowerShell repository.

Please DO a review before fire it up on your productive Exchange Server! You have been warned!

Published inPowerShell

Be First to Comment

Leave a comment

By posting a comment you consent that I store the submitted information as well as your anonymized IP address on my servers, under the terms of my Privacy Policy. Your email is never shared with anyone else.

Required fields are marked *.