When doing TFS upgrades it is useful to know roughly how long they will take. The upgrade programs give a number of steps, but not all steps are equal. Some are quick, some are slow. I have found it useful to graph past updates so I can get a feel of how long an update will take given it got to ‘step x in y minutes’. You can do this by hand, noting down time as specific steps are reached. However for a long upgrade it usually means pulling data out of the TFS TPC upgrade logs.

To make this process easier I put together this script to find the step completion rows in the log file and format them out such that they are easy to graph in Excel

param  
(  
    $logfile = "TPC\_ApplyPatch.log",  
    $outfile = "out.csv"  
) 

  
 # A function to covert the start and end times to a number of minutes  
 # Can't use simple timespan as we only have the time portion not the whole datetime  
 # Hence the hacky added a day-1 second  
 function CalcDuration  
 {  
    param  
    (  
        $startTime,  
        $endTime  
    )

 

    $diff = \[dateTime\]$endTime - $startTime  
    if (\[dateTime\]$endTime -lt $startTime)   
    {   
       $diff += "23:59" # add a day as we past midnight  
    }

 

    \[int\]$diff.Hours \*60 + $diff.Minutes  
 }

 

 Write-Host "Importing $logfile for processing"  
 # pull out the lines we are interested in using a regular expression to extract the columns  
 # the (.{8} handle the fixed width, exact matches are used for the test  
 $lines = Get-Content -Path $logfile | Select-String "  Executing step:"  | Where{$\_ -match "^(.)(.{8})(.{8})(Executing step:)(.{2})(.\*)(')(.\*)(\[(\])(.\*)(\[ \])(\[of\])(.\*)"} | ForEach{  
    \[PSCustomObject\]@{  
        'Step' = $Matches\[10\]  
        'TimeStamp' = $Matches\[2\]  
        'Action' = $Matches\[6\]  
    }  
 }  
   
\# We assume the upgrade started at the timestamp of the 0th step  
\# Not true but very close  
\[DateTime\]$start = $lines\[0\].TimeStamp

 

Write-Host "Writing results to $outfile"  
\# Work out the duration  
 $steps = $lines | ForEach{  
    \[PSCustomObject\]@{  
        'Step' = $\_.Step  
        'TimeStamp' = $\_.TimeStamp  
        'EplasedTime' = CalcDuration -startTime $start -endTime $\_.TimeStamp   
        'Action' = $\_.Action  
          
    }  
 }   
 $steps | export-csv $outfile -NoTypeInformation 

 

\# and list to screen  
$steps