Загрузка данных


$ErrorActionPreference = "Continue"

# ===== НАСТРОЙКА =====
# Если знаешь ящик, на котором ловишь 0x8004010F — укажи здесь.
# Можно оставить пустым.
$Mailbox = ""

$ReportDir = "C:\Temp"
if (!(Test-Path $ReportDir)) {
    New-Item -ItemType Directory -Path $ReportDir -Force | Out-Null
}

$Report = Join-Path $ReportDir ("Exchange-OAB-Diag_{0}.txt" -f (Get-Date -Format "yyyyMMdd_HHmmss"))

Start-Transcript -Path $Report -Force

function Header($Text) {
    Write-Host ""
    Write-Host "============================================================"
    Write-Host $Text
    Write-Host "============================================================"
}

Header "1. BASIC INFORMATION"

Write-Host "Computer:"
$env:COMPUTERNAME

Write-Host "`nDate:"
Get-Date

Write-Host "`nExchange servers:"
Get-ExchangeServer |
    Format-Table Name,ServerRole,Edition,AdminDisplayVersion -AutoSize


Header "2. OFFLINE ADDRESS BOOKS"

try {
    Get-OfflineAddressBook |
        Format-List Name,
                    Identity,
                    AddressLists,
                    GeneratingMailbox,
                    GlobalWebDistributionEnabled,
                    VirtualDirectories,
                    IsDefault,
                    WhenChanged
}
catch {
    Write-Host "ERROR Get-OfflineAddressBook:"
    Write-Host $_
}


Header "3. OAB GENERATION MAILBOX"

try {
    Get-Mailbox -Arbitration -ResultSize Unlimited |
        Where-Object {
            $_.PersistedCapabilities -match "OAB"
        } |
        Format-List Name,
                    Alias,
                    DisplayName,
                    ServerName,
                    Database,
                    PersistedCapabilities
}
catch {
    Write-Host "ERROR OAB arbitration mailbox:"
    Write-Host $_
}


Header "4. OAB VIRTUAL DIRECTORIES"

try {
    Get-OabVirtualDirectory |
        Format-List Identity,
                    Server,
                    InternalUrl,
                    ExternalUrl,
                    RequireSSL,
                    BasicAuthentication,
                    WindowsAuthentication
}
catch {
    Write-Host "ERROR Get-OabVirtualDirectory:"
    Write-Host $_
}


Header "5. AUTODISCOVER SCP"

if (Get-Command Get-ClientAccessService -ErrorAction SilentlyContinue) {
    Get-ClientAccessService |
        Format-List Name,
                    AutoDiscoverServiceInternalUri
}
elseif (Get-Command Get-ClientAccessServer -ErrorAction SilentlyContinue) {
    Get-ClientAccessServer |
        Format-List Name,
                    AutoDiscoverServiceInternalUri
}
else {
    Write-Host "Get-ClientAccessService/Get-ClientAccessServer unavailable."
}


Header "6. MAILBOX DATABASE -> OAB MAPPING"

try {
    Get-MailboxDatabase -Status |
        Format-Table Name,
                     Server,
                     Mounted,
                     OfflineAddressBook -AutoSize
}
catch {
    Write-Host "ERROR Get-MailboxDatabase:"
    Write-Host $_
}


Header "7. ADDRESS BOOK POLICIES"

if (Get-Command Get-AddressBookPolicy -ErrorAction SilentlyContinue) {
    try {
        Get-AddressBookPolicy |
            Format-List Name,
                        AddressLists,
                        GlobalAddressList,
                        OfflineAddressBook,
                        RoomList
    }
    catch {
        Write-Host $_
    }
}
else {
    Write-Host "Get-AddressBookPolicy unavailable."
}


Header "8. MAILBOX-SPECIFIC CHECK"

if ([string]::IsNullOrWhiteSpace($Mailbox)) {

    Write-Host "Mailbox variable is empty - mailbox-specific test skipped."
    Write-Host 'To test a user, set at the start: $Mailbox = "user@domain.ru"'

}
else {

    try {
        $Mbx = Get-Mailbox $Mailbox -ErrorAction Stop

        $Mbx |
            Format-List Name,
                        PrimarySmtpAddress,
                        ServerName,
                        Database,
                        AddressBookPolicy,
                        RecipientTypeDetails

        Write-Host "`nMailbox database configuration:"

        Get-MailboxDatabase $Mbx.Database |
            Format-List Name,
                        Server,
                        OfflineAddressBook

        if ($Mbx.AddressBookPolicy) {

            Write-Host "`nMailbox Address Book Policy:"

            Get-AddressBookPolicy $Mbx.AddressBookPolicy |
                Format-List Name,
                            GlobalAddressList,
                            OfflineAddressBook,
                            AddressLists,
                            RoomList
        }
    }
    catch {
        Write-Host "ERROR mailbox check:"
        Write-Host $_
    }
}


Header "9. IIS OAB APPLICATION"

try {

    Import-Module WebAdministration -ErrorAction Stop

    Write-Host "`nOAB applications:"
    Get-WebApplication |
        Where-Object {
            $_.Path -match "OAB"
        } |
        Format-Table Path,ApplicationPool,PhysicalPath -AutoSize

    Write-Host "`nMSExchangeOABAppPool:"

    if (Test-Path "IIS:\AppPools\MSExchangeOABAppPool") {

        Get-WebAppPoolState "MSExchangeOABAppPool"

        Get-Item "IIS:\AppPools\MSExchangeOABAppPool" |
            Format-List Name,
                        State,
                        managedRuntimeVersion,
                        startMode
    }
    else {
        Write-Host "MSExchangeOABAppPool not found on this server."
    }

}
catch {
    Write-Host "IIS check unavailable/error:"
    Write-Host $_
}


Header "10. LOCAL OAB FILES"

$ExchangePath = $env:ExchangeInstallPath

if ($ExchangePath) {

    $OABPath = Join-Path $ExchangePath "ClientAccess\OAB"

    Write-Host "Expected path:"
    Write-Host $OABPath

    if (Test-Path $OABPath) {

        Write-Host "`nNewest OAB files:"

        Get-ChildItem $OABPath -Recurse -File -ErrorAction SilentlyContinue |
            Sort-Object LastWriteTime -Descending |
            Select-Object -First 30 FullName,
                                    Length,
                                    LastWriteTime |
            Format-Table -AutoSize
    }
    else {
        Write-Host "OAB directory does not exist on this server."
    }
}
else {
    Write-Host "ExchangeInstallPath environment variable not found."
}


Header "11. OAB URL DNS / HTTP CHECK"

try {

    $OabUrls = Get-OabVirtualDirectory |
        ForEach-Object {
            $_.InternalUrl
            $_.ExternalUrl
        } |
        Where-Object { $_ } |
        Select-Object -Unique

    foreach ($Url in $OabUrls) {

        Write-Host ""
        Write-Host "----- $Url -----"

        try {
            $Uri = [Uri]$Url

            Write-Host "Host: $($Uri.Host)"

            Write-Host "`nDNS:"
            Resolve-DnsName $Uri.Host -ErrorAction Stop |
                Format-Table Name,Type,IPAddress -AutoSize

        }
        catch {
            Write-Host "DNS ERROR:"
            Write-Host $_.Exception.Message
        }

        try {

            Write-Host "`nHTTP test:"

            $Response = Invoke-WebRequest `
                -Uri $Url `
                -Method Head `
                -UseBasicParsing `
                -MaximumRedirection 0 `
                -TimeoutSec 10 `
                -ErrorAction Stop

            Write-Host "HTTP status: $($Response.StatusCode)"

        }
        catch {

            if ($_.Exception.Response) {

                try {
                    $Status = [int]$_.Exception.Response.StatusCode
                    Write-Host "HTTP status: $Status"
                }
                catch {
                    Write-Host $_.Exception.Message
                }

            }
            else {
                Write-Host "HTTP ERROR:"
                Write-Host $_.Exception.Message
            }
        }
    }

}
catch {
    Write-Host "OAB URL test error:"
    Write-Host $_
}


Header "12. EXCHANGE HEALTH - OAB / AUTODISCOVER"

if (Get-Command Get-ServerHealth -ErrorAction SilentlyContinue) {

    try {

        Get-ExchangeServer |
            ForEach-Object {

                $Server = $_.Name

                Write-Host ""
                Write-Host "SERVER: $Server"

                Get-ServerHealth -Identity $Server -ErrorAction SilentlyContinue |
                    Where-Object {
                        $_.HealthSetName -match "OAB|Autodiscover" -or
                        $_.Name -match "OAB|Autodiscover"
                    } |
                    Format-Table Server,
                                 HealthSetName,
                                 Name,
                                 AlertValue,
                                 State -AutoSize
            }
    }
    catch {
        Write-Host "Health check error:"
        Write-Host $_
    }
}
else {
    Write-Host "Get-ServerHealth unavailable."
}


Header "13. RECENT EXCHANGE OAB / AUTODISCOVER ERRORS"

try {

    $Start = (Get-Date).AddDays(-3)

    Get-WinEvent `
        -FilterHashtable @{
            LogName   = "Application"
            StartTime = $Start
            Level     = 2,3
        } `
        -ErrorAction SilentlyContinue |

        Where-Object {
            $_.ProviderName -match "Exchange" -and
            $_.Message -match "OAB|Offline Address Book|Autodiscover"
        } |

        Select-Object -First 50 `
            TimeCreated,
            ProviderName,
            Id,
            LevelDisplayName,
            Message |

        Format-List

}
catch {
    Write-Host "Event log query error:"
    Write-Host $_
}


Header "14. IMPORTANT EXCHANGE SERVICES"

Get-Service |
    Where-Object {
        $_.Name -match "^MSExchange"
    } |
    Sort-Object Name |
    Format-Table Status,
                 StartType,
                 Name,
                 DisplayName -AutoSize


Header "DIAGNOSTICS COMPLETE"

Write-Host ""
Write-Host "REPORT SAVED TO:"
Write-Host $Report
Write-Host ""

Stop-Transcript