As I wrote in a previous post, I began using the new DFS Replication database cloning technique to speed up initial sync. Thanks to Ned Pyle’s great How-To on the subject, I was able to tell exactly which events to look for in the event log to get an idea of progress: 2412 for the start of the process, 2416 for progress, 2404 for successful finish, and 2418 for an unsuccessful end (found that one out on my own, whoops!).

Since I clearly had a few hours to kill while the import happened, I wrote up a quick script to show the progress, with estimated time remaining.

Script Details

This is a quick-and-dirty powershell script with no fancy CmdletBinding or any parameters at all, and no comments, and barely any testing so use at your own risk, etc.

The basic idea is that it keeps checking the event log (I’m doing it every 5 seconds), looking for new progress events, and it uses Write-Progress to display some pretty stats. When the event 2404 indicates a successful completion or 2418 indicates an error, it should end the script or raise an exception, respectively.

In the meantime, you’ll just see the progress:

DFSR-Import-Progress

The progress bar is only updated when a new event is logged, so you won’t see continuously changing numbers. It’s more of a thing you leave running in the background and check on every now and then.

Oh and it doesn’t have to be run on the machine doing the import, so it can be run from a management server or desktop client to keep tabs on the progress. Since it uses events in the event log on the destination computer, stopping and restarting the script will still give you consistent progress.

The Full Script

$importComputer = 'ComputerName'

$clonestart = Get-WinEvent -FilterHashtable @{LogName='DFS Replication';ID=2412} -ComputerName $importComputer -MaxEvents 1 -ErrorAction SilentlyContinue
$start = $null
if ($clonestart) {
    $start = $clonestart.TimeCreated
} else {
    throw "No clone event found."
}

$progtime = $start

for() {
    $cloneend = Get-WinEvent -FilterHashtable @{LogName='DFS Replication';ID=2404} -ComputerName $importComputer -MaxEvents 1 -ErrorAction SilentlyContinue
    if ($cloneend) {
        if ($cloneend.TimeCreated -gt $start) {
            # Clone import successfully finished.
            Write-Progress -Activity 'Importing DFSr Database' -Completed
            break
        }
    }
    $cloneerr = Get-WinEvent -FilterHashtable @{LogName='DFS Replication';ID=2414} -ComputerName $importComputer -MaxEvents 1 -ErrorAction SilentlyContinue
    if ($cloneerr) {
        if ($cloneerr.TimeCreated -gt $start) {
            throw "Clone import error:\n$cloneerr"
        }
    }
    $cloneprog = Get-WinEvent -FilterHashtable @{LogName='DFS Replication';ID=2416} -ComputerName $importComputer -MaxEvents 1 -ErrorAction SilentlyContinue
    if ($cloneprog) {
        if ($cloneprog.TimeCreated -gt $progtime) {
            $progtime = $cloneprog.TimeCreated
            if ($cloneprog.Message -imatch '(?s)Processed:(\d+).*?Remaining:(\d+)') {
                $processed = [Int64]::Parse($Matches[1])
                $remaining = [Int64]::Parse($Matches[2])
                $total = $processed + $remaining
                $percentage = (($processed*100.0)/$total)
                $elapsed = ($progtime - $start).TotalSeconds
                $secrem = ($elapsed*(100.0/$percentage)) - $elapsed
                $submessage = "$("{0:N0}" -f $processed) records of $("{0:N0}" -f $total) ($("{0:N0}" -f $remaining) remaining) - $("{0:N2}" -f $percentage)% :: Last Update: $progtime, $(($progtime - $start)) elapsed"
                Write-Progress -Activity 'Importing DFSr Database' -Status $submessage -PercentComplete $percentage -SecondsRemaining $secrem
            }
        }
    }
    Start-Sleep -Seconds 5
}