Reviewing Message Tracking Logs from other Servers and/or Restored Backups

We had a case come in a few months ago where we were restoring Message Tracking Logs from backups and couldn’t use the Get-MessageTrackingLog properly when specifying an –EndDate parameter. Consequently, we run into this same problem when trying to load up logs from other servers as well.

Basically, Exchange documentation states the following (at least as of this posting):

https://technet.microsoft.com/en-us/library/bb124926.aspx

You can't copy the message tracking logs from an Exchange server and then use the Get-MessageTrackingLog cmdlet or the Message Tracking tool to search the copied logs on a different Exchange server. Also, if you save an existing message tracking log, the change in the date-time stamp of the message tracking log file breaks the query logic that is used to search the message tracking logs.

If the CreationTime and/or LastModified time stamps of an old message tracking log change, unexpected behavior can arise. Without going into details, the Log Search service uses this information to help speed up search requests within specified date ranges. These times can be off by copying the files from one server to another, restoring the logs from certain backups, opening a log up in notepad and saving it, etc,.

I wrote the powershell script below to help work around this problem. It goes through each tracking log in the message tracking log directories for both Hub and Mailbox roles, fixes the CreationTime and LastModified time based on the first and last entry in the log and restarts the Log Search service so that the changes will be picked up. It does require that you stop the Information Store and/or Transport Service before running the script. A small price to pay for fixing the log files. The point of requiring the service to be stopped is to get exclusive access to the files lest one is being written to by the service when we try to modify it.

Note: Entirely unsupported. Your mileage may vary.

#=================================================
# FixTrackingLogs Script by Stuart Presley
# This script will fix message tracking logs so
# that they can be imported from another machine
# and reviewed with the -EndDate parameter on
# Get-MessageTrackingLogs
# Use at your own risk. Make file level backups
# of the tracking log files before running
#
# Requires: Exchange Management Shell
# Usage: .\FixTrackingLogs.ps1
#
#=================================================

function GetMachineName
{
(Get-WmiObject Win32_ComputerSystem).Name;
}

function ReadFile($item)
{
$file = [System.IO.File]::OpenText($item.FullName)

#Get the first date entry...ignoring the first 5 lines
for($count = 0; $count -le 5; $count++)
{
$line = $file.ReadLine()
}

$linearray = $line.Split(',')

#Get the date
$CreationTime = $linearray[0]

#now lets get the last date
while($file.EndOfStream -ne $true)
{
$line = $file.ReadLine()
}

$linearray = $line.Split(',')
$LastModifiedTime = $linearray[0]
$LastAccessTime = $CreationTime

#now lets fix the times
$file.Close()
$item.CreationTime = [System.DateTime]::Parse($CreationTime)
$item.LastWriteTime = [System.DateTime]::Parse($LastModifiedTime)
$item.LastAccessTime = [System.DateTime]::Parse($LastAccessTime)
}

function FixTrackingLogs
{
Write-Warning "It is highly suggested that you make a file level backup of your message tracking logs before running this script"
$confirm = Read-Host "Run this script at your own risk. Are you sure you wish to continue (Y/N)"

if(!$confirm.ToLower().StartsWith("y"))
{
break
}

$machinename = GetMachineName
$server = Get-ExchangeServer -Identity $machinename
$MSExchangeIS = Get-Service MSExchangeIS
$MSExchangeTransport = Get-Service MSExchangeTransport

if($MSExchangeIS.Status -ieq "Running" -or $MSExchangeTransport.Status -ieq "Running")
{
Write-Warning "The Microsoft Exchange Information Store or Microsoft Exchange Transport Service is running"
Write-Warning "You must stop these services before running this script"
break
}

if($server.IsMailboxServer)
{
$MailboxServer = Get-MailboxServer -Identity $machinename
$MailboxMessageTrackingLogPath = $MailboxServer.MessageTrackingLogPath.PathName
$dir = Get-ChildItem $MailboxMessageTrackingLogPath
Write-Host "Updating Mailbox tracking logs at $MailboxMessageTrackingLogPath"
GetTrackingLogs($dir)
}

if($server.IsHubTransportServer -or $server.IsEdgeServer)
{
$transportServer = Get-TransportServer -Identity $machinename
$TransportServerTrackingLogPath =
$transportServer.MessageTrackingLogPath.PathName

if($server.IsMailboxServer -and $MailboxMessageTrackingLogPath -eq $TransportServerTrackingLogPath)
{
###Don't do anything...the files have already been processed.
Write-Host "Mailbox and Hub Transport Role share same log path...no need to
update Hub."
}
else
{
Write-Host "Updating TransportServer Tracking Logs at $TransportServerTrackingLogPath"
$dir = Get-ChildItem $TransportServerTrackingLogPath
GetTrackingLogs($dir)
}
}

Write-Host "Restarting the Microsoft Exchange Transport Log Search Service"
restart-Service MSExchangeTransportLogSearch
}

function GetTrackingLogs($dir)
{
foreach($item in $dir)
{
#Rule out directories and only get MSGTRK files...

if($item.mode -ne "d----" -and $item.Name -ilike("MSGTRK*"))
{
#$item.CreationTime = [System.DateTime]::Now
#$item.LastWriteTime = [System.DateTime]::Now
#$item.LastAccessTime = [System.DateTime]::Now
ReadFile($item)
}
}
}

FixTrackingLogs

#************************************************************************