Description

A sample PowerShell script to track down calendar items contributing to the symptoms that persist after applying the workaround detailed above. This script will identify the day containing problem appointments and can be run against a specific mailbox or all Exchange 2007 mailboxes.  The requirements for running the script are detailed in the script comments. The sample script uses the $true argument to enumerate all Exchange 2007 mailboxes and user42@contoso.com to initialize the Autodiscover portion of the Web Services object.

It goes with the following blog post:

http://msexchangeteam.com/archive/2010/01/11/453755.aspx

Script

PowerShell
Edit|Remove
################################################################################# 
 
# The sample scripts are not supported under any Microsoft standard support  
# program or service. The sample scripts are provided AS IS without warranty  
# of any kind. Microsoft further disclaims all implied warranties including, without  
# limitation, any implied warranties of merchantability or of fitness for a particular  
# purpose. The entire risk arising out of the use or performance of the sample scripts  
# and documentation remains with you. In no event shall Microsoft, its authors, or  
# anyone else involved in the creation, production, or delivery of the scripts be liable  
# for any damages whatsoever (including, without limitation, damages for loss of business  
# profits, business interruption, loss of business information, or other pecuniary loss)  
# arising out of the use of or inability to use the sample scripts or documentation,  
# even if Microsoft has been advised of the possibility of such damages 
# 
################################################################################# 
# 
# Find-BadCalendarItems 
# 
# This script finds calendar items that are breaking availability lookup. It does 
# this by performing an availability query against users, and narrowing it down 
# to the specific day that's causing the failure. The user will need to manually 
# examine each appointment on that day to find the one causing the problem. 
# 
# Requirements: 
# 
# This script must be run from a shell that has access to the Get-Mailbox command 
# if $checkAllUsers is $true. The script also requires the EWS managed API, which 
# can be downloaded here: 
# http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=c3342fb3-fbcc-4127-becf-872c746840e1 
# Make sure the Import-Module command below matches the DLL location of the API. 
# 
# Syntax: 
# 
# To run against a single user: 
# 
# .\Find-BadCalendarItems user1@contoso.com $false 
# 
# In that case, we only check the user1@contoso.com calendar. 
# 
# To run against all users: 
# 
# .\Find-BadCalendarItems user1@contoso.com $true 
# 
# In this case we use user1@contoso.com to do autodiscovery, but we check all users. 
 
param([string]$proxy, [bool]$checkAllMailboxes) 
 
########## 
# 
# This path must match the install location of the EWS managed API. Change it if needed. 
 
Import-Module -Name "C:\Program Files\Microsoft\Exchange\Web Services\1.0\Microsoft.Exchange.WebServices.dll" 
 
########## 
 
if ($proxy.Length -lt 1) 
{ 
    "Invalid syntax." 
    return 
} 
 
function CheckMailbox($exchService$mailbox) 
{ 
    Write-Host ("Checking mailbox: " + $mailbox) 
    $current = [DateTime]::Today 
    $attendeeInfo = new-object Microsoft.Exchange.WebServices.Data.AttendeeInfo($mailbox) 
    [Microsoft.Exchange.WebServices.Data.AttendeeInfo[]]$attendeeInfos = ( $attendeeInfo ) 
    [Microsoft.Exchange.WebServices.Data.TimeWindow[]]$failedWindows = @() 
    $startTime = $current.Subtract([TimeSpan]::FromDays(180)) 
    for ($x = 0; $x -lt 12; $x++) 
    { 
        $timeWindow = new-object Microsoft.Exchange.WebServices.Data.TimeWindow($startTime$startTime.AddDays(30)) 
        $availResults = $exchService.GetUserAvailability($attendeeInfos$timeWindow, [Microsoft.Exchange.WebServices.Data.AvailabilityData]::FreeBusy) 
        foreach ($result in $availResults.AttendeesAvailability) 
        { 
            if ($result.ErrorCode -eq [Microsoft.Exchange.WebServices.Data.ServiceError]::NoError) 
            { 
                # Write-Host ("Succeeded: " + $startTime.ToShortDateString() + " - " + $startTime.AddDays(30).ToShortDateString()) 
            } 
            else 
            { 
                Write-Host ("Failed : " + $startTime.ToShortDateString() + " - " + $startTime.AddDays(30).ToShortDateString()) 
                Write-Host ("         Error: " + $result.ErrorMessage) 
                $failedWindows +new-object Microsoft.Exchange.WebServices.Data.TimeWindow($startTime$startTime.AddDays(30)) 
            } 
        } 
        $startTime = $startTime.AddDays(30) 
    } 
 
    [Microsoft.Exchange.WebServices.Data.TimeWindow[]]$problemWindows = @() 
    foreach ($timeWindow in $failedWindows) 
    { 
        # This is a 30-day time window. We need to break it down to try and find the problem. 
        # Let's do each day individually. 
        for ($x = 0; $x -lt 30; $x++) 
        { 
            $dayWindow = new-object Microsoft.Exchange.WebServices.Data.TimeWindow($timeWindow.StartTime.AddDays($x), $timeWindow.StartTime.AddDays($x+1)) 
            $availResults = $exchService.GetUserAvailability($attendeeInfos$dayWindow, [Microsoft.Exchange.WebServices.Data.AvailabilityData]::FreeBusy) 
            foreach ($result in $availResults.AttendeesAvailability) 
            { 
                if ($result.ErrorCode -eq [Microsoft.Exchange.WebServices.Data.ServiceError]::NoError) 
                { 
                    # Write-Host ("Day succeeded: " + $dayWindow.StartTime.ToShortDateString()) 
                } 
                else 
                { 
                    Write-Host ("Day failed: " + $dayWindow.StartTime.ToShortDateString()) 
                    $problemWindows +$dayWindow 
                } 
            } 
        } 
    } 
 
    if ($problemWindows.Length -gt 0) 
    { 
        $problemString = $mailbox + ": " 
        foreach ($window in $problemWindows) 
        { 
            $problemString +$window.StartTime.ToShortDateString() + " " 
        } 
         
        return $problemString 
    } 
     
    return "" 
} 
 
$exchService = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1) 
$exchService.UseDefaultCredentials = $true 
$exchService.AutodiscoverUrl($proxy) 
 
if (!($checkAllMailboxes)) 
{ 
    $result = CheckMailbox $exchService $proxy 
    if ($result.Length -gt 0) 
    { 
        "Problem days found:" 
        $result 
    } 
    else 
    { 
        "No problems found." 
    } 
} 
else 
{ 
######### 
# 
# If you want to control the group of mailboxes it runs against, modify this command. 
# Currently, the command only runs against all Exchange 2007 mailboxes. 
# 
    $mailboxes = Get-Mailbox -ResultSize unlimited | where { $_.ExchangeVersion -like "0.1 (8*"# 
######### 
    [string[]]$problems = @() 
    foreach ($mailbox in $mailboxes) 
    { 
        $result = CheckMailbox $exchService $mailbox.PrimarySmtpAddress.ToString() 
        if ($result.Length -gt 0) 
        { 
            $problems +$result 
        } 
    } 
    if ($problems.Length -gt 0) 
    { 
        "Problems found:" 
        $problems 
    } 
    else 
    { 
        "No problems found." 
    } 
} 
 
"Done!"