Exchange: Alte OWA/ECP Daten löschen

Exchange Server lassen nach nahezu jedem Update alte Daten bzw. Versionen der OWA und ECP Verzeichnisse auf dem Dateisystem liegen. Insbesondere das Verzeichnis „C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\Owa\prem“ belegt nach längerer Laufzeit und entsprechend vielen Updates doch einigen Platz auf dem Dateisystem. Hier mal ein Beispiel von einem Exchange Server der schon etwas länger läuft:

Alte Dateiversionen / Daten im Verzeichnis „prem“ belegen hier immerhin 16 GB auf dem Dateisystem. Genutzt werden diese Daten nicht mehr. Frank C. (msXfaq) hat zu diesem Thema einen lesenswerten Artikel erstellt:

https://www.msxfaq.de/exchange/update/alte_owa_dateien_loeschen.htm

Zwar dürften die „paar“ GB die wenigstens Leute aus der Ruhe bringen, aber es könnte ja mal knapp werden mit dem Speicherplatz. Wenn ein Laufwerk droht vollzulaufen, macht es also Sinn, wenn man weiß wo man sich etwas Luft zum Atmen verschaffen kann. Neben den Logfiles der Exchange Server lässt sich also auch hier etwas Speicherplatz gewinnen.

Frank C. hat in seinem Artikel auch den folgenden Satz stehen:

Das Löschen alter Versionen könnten Sie natürlich auch per PowerShell o.ä. automatisieren.

Quelle: https://www.msxfaq.de/exchange/update/alte_owa_dateien_loeschen.htm

Den Satz habe ich mal aufgenommen und in ein PowerShell Script umgewandelt. Das nachstehende PowerShell Script listet alle alten Versionsstände in den folgenden Verzeichnissen auf:

  • $exinstall\ClientAccess\ecp
  • $exinstall\ClientAccess\Owa
  • $exinstall\ClientAccess\Owa\prem

Zur Sicherheit ermittelt das Script die älteste Exchange Server Version (in Umgebungen mit mehreren Exchange Servern) und listet alle Versionen der Verzeichnisse auf, die älter als der älteste Exchange Server sind. Somit bleibt gewährleistet, dass die Verzeichnisversionen passend zum Build des ältesten Exchange Servers vorhanden bleiben und nicht gelöscht werden.

Das Script listet beim Ausführen nur die alten Verzeichnisversionen auf, löscht diese aber nicht. Erst wenn der Parameter „-$DeleteOldVersions:$true“ angegeben wird, werden die Daten auch gelöscht.

Hier nun das Script, welches in eine .PS1 Datei kopiert werden kann:

<#
    .SYNOPSIS
     Identifies, reports and deletes old OWA / ECP folders
    .DESCRIPTION
     Run this Script to list old and unused OWA / ECP folder. Set Parameter -DeleteOldVersions to $true if you
     want to delete old folders to free up disk space.
    .PARAMETER DeleteOldVersions
     Set DeleteOldVersions to $True to delete old OWA / ECP folder versions.
    .EXAMPLE
     .\Delete-OldFolderVersions.ps1
     List old OWA / ECP folderversions:
    .EXAMPLE
     .\Delete-OldFolderVersions.ps1 -DeleteOldVersions $true
     List and delete old OWA / ECP Directory versions:
    .NOTES
     Author:  Frank Zoechling
     Website: https://www.frankysweb.de
     Twitter: @FrankysWeb
#>
 
Param(
    [Parameter(Mandatory=$False)]
    [bool]$DeleteOldVersions
)
 
# Test if evelated Shell
Function Confirm-Administrator {
    $currentPrincipal = New-Object Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurrent() )
    if ($currentPrincipal.IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator )) {
        return $true
    } else {
        return $false
    }
}
 
if (-not (Confirm-Administrator)) {
    Write-Output $msgNewLine
    Write-Warning "This script needs to be executed in elevated mode. Start the Exchange Management Shell as an Administrator and try again."
    $Error.Clear()
    Start-Sleep -Seconds 2
    exit
}
 
#Foldernames to search for old ECP / OWA folders
$ECPFolderPath = $exinstall + "ClientAccess\ecp"
$OWAFolderPath = $exinstall + "ClientAccess\Owa"
$OWAPremFolderPath = $exinstall + "ClientAccess\Owa\prem"
 
#Get Exchange Server Versions
try {
    $ExchangeServerVersions = @()
    $ExchangeServerDisplayVersions = (Get-ExchangeServer | Where-Object { $_.AdminDisplayVersion.Major -eq 15 }).AdminDisplayVersion
    foreach ($ExchangeServerDisplayVersion in $ExchangeServerDisplayVersions) {
        $ExchangeServerVersions += $ExchangeServerDisplayVersion.Major,$ExchangeServerDisplayVersion.Minor,$ExchangeServerDisplayVersion.Build,$ExchangeServerDisplayVersion.Revision -join "."
    }
    $ExchangeServerVersion = $ExchangeServerVersions | Sort-Object | Select-Object -first 1
    write-host ""
    write-host "Oldest installed Exchange Build is: $ExchangeServerVersion"
    write-host ""
} catch {}
 
 
#Search all OWA / ECP folder versions
try {
    $AllVersions = @()
    $AllVersions += Get-ChildItem $ECPFolderPath -Directory | Where-Object { $_.Name.StartsWith("15.") } | Select-Object FullName,Name
    $AllVersions += Get-ChildItem $OWAFolderPath -Directory | Where-Object { $_.Name.StartsWith("15.") } | Select-Object FullName,Name
    $AllVersions += Get-ChildItem $OWAPremFolderPath -Directory | Where-Object { $_.Name.StartsWith("15.") } | Select-Object FullName,Name
} catch {}
 
#Search for old versions
write-host "Old OWA / ECP folders:"
write-host ""
$ExchangeBuild = [System.Version]::Parse($exchangeserverversion)
$OldVersions = @()
foreach ($Version in $AllVersions)  {
    $Folderversion = [System.Version]::Parse($Version.Name)
    if ( $Folderversion -lt $ExchangeBuild ) {
        write-host $Version.Fullname
        $OldVersions += $Version.Fullname
    }
}
write-host ""
 
#Delete old OWA / ECP folder versions
if ($DeleteOldVersions -eq $true) {
    write-host "Deleting old OWA / ECP versions:"
    write-host ""
    foreach ($Oldversion in $OldVersions) {
        write-host $Oldversion
        Remove-Item $Oldversion -Recurse -Confirm:$true
    }
}

Wer es etwas einfacher haben möchte, das Script habe ich auch auf GitHub veröffentlicht:

Update 07.12.2021: Das Script wurde aktualisiert damit mehr ältere Versionen erfasst werden, die Änderungen lassen sich auf GitHub nachvollziehen. Vielen Dank für den Pull Request.

26 thoughts on “Exchange: Alte OWA/ECP Daten löschen”

  1. Hallo Frank, ich habe das Skript in der Vergangenheit erfolgreich genutzt. Nach Update auf Build 1544.4.11 funktioniert die Ermittlung der installierten Exchange Versionen nicht mehr.

    (Get-ExchangeServer).AdminDisplayVersion liefert „Version 15.2 (Build 1544.4)“. Die Felder „Major“ usw. gibt es scheinbar nicht mehr.
    Daher liefert die folgende Zeile im Skript keinen Wert:

    $ExchangeServerDisplayVersions = (Get-ExchangeServer | Where-Object { $_.AdminDisplayVersion.Major -eq 15 }).AdminDisplayVersion

    In der Folge kommt dann dieser Fehler in Zeile 76:

    Ausnahme beim Aufrufen von „Parse“ mit 1 Argument(en): „Der Wert darf nicht NULL sein.
    Parametername: input“
    In D:\Delete-OldFolderVersions.ps1:76 Zeichen:1
    + $ExchangeBuild = [System.Version]::Parse($exchangeserverversion)

    Reply
  2. Hallo Frank,

    heute, zwei Jahre nachdem du diesen Beitrag geschrieben hast, hilfst du immer noch Menschen, die im Internet nach Lösungen für Exchange-Probleme suchen, und bietest hier eine Heimat für Wissen.

    Ich möchte dir hiermit nur meinen Dank aussprechen und dir weiterhin viel Erfolg in deiner Karriere wünschen.

    Alles Gute,
    L. Correia

    Reply
  3. Letzte Version des Scripts von GitHub geladen und elevated ausgeführt.
    Folgende Ausgabe:
    ###############
    Oldest installed Exchange Build is: 15.2.1118.7

    Old OWA / ECP folders:

    ###############

    Also unterhalb von „Old OWA / ECP folders:“ steht einfach mal gar nichts.
    C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\Owa beherbergt aber durchaus 8,04 GB und hat u.a. die Unterordner
    15.2.1118.7 15.2.1118.12 15.2.1118.26
    Wer macht da was falsch: Ich? Das Skript? Mein eventueller Vorgänger der auf der an Platz knappen Maschine gg.f schon etwas per Hand herausoperiert hat???

    Reply
  4. Super Skript.
    Da ich bei mir privat nur einen einzigen Domain Controller sowie nur einen einzigen Exchange Server habe (auf der selben Maschine),
    kann ich im grundsätzlich problemlos ALLE alten Versionen löschen.
    Es gibt für mich in aller Regel Null Gründe, zu einer alten Version zurückzukehren.
    WENN Fehler auftreten, habe ich eben eine kurze Downzeit, tut mir als Privatperson aber nicht SO sehr weh,
    da Strato als Backup-MX fungiert und die Mails vorläufig entgegennehmen würde.

    Reply
  5. Danke für das feine Script! Das hilft wirtschaften.

    Bei meinen Tests hat es aber bei jedem Verzeichnis trotz „A“ Auswahl immer wieder nachgefragt:

    Ausführen des Vorgangs „Verzeichnis entfernen“ für das Ziel „C:\Program Files\Microsoft\Exchange
    Server\V15\ClientAccess\Owa\15.1.845.34“.
    [J] Ja [A] Ja, alle [N] Nein [K] Nein, keine [H] Anhalten [?] Hilfe (Standard ist „J“): A
    C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\Owa\15.1.845.36

    Bestätigung
    Möchten Sie diese Aktion wirklich ausführen?
    Ausführen des Vorgangs „Verzeichnis entfernen“ für das Ziel „C:\Program Files\Microsoft\Exchange
    Server\V15\ClientAccess\Owa\15.1.845.36“.
    [J] Ja [A] Ja, alle [N] Nein [K] Nein, keine [H] Anhalten [?] Hilfe (Standard ist „J“): A
    C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\Owa\prem\15.1.1466.3

    Bestätigung
    Möchten Sie diese Aktion wirklich ausführen?
    Ausführen des Vorgangs „Verzeichnis entfernen“ für das Ziel „C:\Program Files\Microsoft\Exchange
    Server\V15\ClientAccess\Owa\prem\15.1.1466.3“.
    [J] Ja [A] Ja, alle [N] Nein [K] Nein, keine [H] Anhalten [?] Hilfe (Standard ist „J“): A
    C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\Owa\prem\15.1.1713.1

    Bestätigung
    Möchten Sie diese Aktion wirklich ausführen?
    Ausführen des Vorgangs „Verzeichnis entfernen“ für das Ziel „C:\Program Files\Microsoft\Exchange
    Server\V15\ClientAccess\Owa\prem\15.1.1713.1“.
    [J] Ja [A] Ja, alle [N] Nein [K] Nein, keine [H] Anhalten [?] Hilfe (Standard ist „J“): A
    C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\Owa\prem\15.1.1779.2

    Bestätigung
    Möchten Sie diese Aktion wirklich ausführen?
    Ausführen des Vorgangs „Verzeichnis entfernen“ für das Ziel „C:\Program Files\Microsoft\Exchange
    Server\V15\ClientAccess\Owa\prem\15.1.1779.2“.
    [J] Ja [A] Ja, alle [N] Nein [K] Nein, keine [H] Anhalten [?] Hilfe (Standard ist „J“): A
    C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\Owa\prem\15.1.1779.3

    Bestätigung
    Möchten Sie diese Aktion wirklich ausführen?
    Ausführen des Vorgangs „Verzeichnis entfernen“ für das Ziel „C:\Program Files\Microsoft\Exchange
    Server\V15\ClientAccess\Owa\prem\15.1.1779.3“.
    [J] Ja [A] Ja, alle [N] Nein [K] Nein, keine [H] Anhalten [?] Hilfe (Standard ist „J“):

    Mache ich da was falsch?

    Reply
  6. Danke für dein Script, ich warte schon lange auf eine Lösung für dieses Kumulieren von alten Dateien. Inzwischen sind das bei mir >40GB, die in jedes Backup (inkl. Aufbewahrung mehrerer Zeitpunkte) eingehen, das läppert sich und kostet Backupspeicher und Backupzeit.

    Aktuell lasse ich das Script noch etwas „reifen“ und habe das Delete noch nicht aktiv ausführen lassen.

    Bei der Prüfung fällt mir aber schon folgendes auf (ich habe 1x Exchange 2016 mit letztem CU und Updates):
    >>Oldest installed Exchange Build is: 15.1.2375.7

    Ich finde aber Ordner mit 15.1.2375.12 und 15.1.2375.17.

    Grund ist wohl der schlampige Umgang von MS mit Versionsinfos. Im Exchange Admin Center wird mir auch nur build 2375.7 angezeigt, die ExSetup.exe hat aber in ihren Eigenschaften das neueste build 2375.17 (siehe https://community.spiceworks.com/topic/2337762-unable-to-update-to-exchange-2016-15-1-2375-12)

    Grund ist, dass im AD die Version nicht exakt mitgepflegt wird.

    Beim Einsatz des Scriptes werden also aus diesem Grund immer ein paar Ordner nicht gelöscht werden, obwohl der Exchange schon neueren Datums ist. Aber das ist verschmerzbar, wenn es nicht sogar noch Vorteile in manchen Umgebungen hat.

    Reply
  7. In Zeile 82 vom Script musste ich eine Anpassung mache, da sonst ich ständig mit „Y“ oder „A“ bestätigen muss zum löschen.
    Anstatt „Remove-Item $Oldversion -Recurse -Confirm:$true“ zu nehmen habe ich „Remove-Item $Oldversion -Recurse -ErrorAction SilentlyContinue“ verwendet. Damit löscht es die Ordner ohne zu fragen. Ich verwende Exchange 2013 mit Server 2012 R2.

    Gruß
    Simon

    Reply
  8. Ist das eigentlich ein Bug oder eine Feature das diese Leichen über bleiben? Ich find es eine Schande das Microsoft das nicht in Griff bekommt.

    Danke Franky für das script, mein innerer Monk ist damit befriedigt!

    Reply
    • Das ist kein Bug und auch kein Feature sondern unter Umständen notwendig wenn da mehrere Server vernetzt sind. Im MSXfaq Artikel ist beschrieben warum manchmal die alte Version gebraucht wird.

      Reply
  9. Hi,
    ja, wieder ein prima Script, merci vielmals !
    Ich frage mich nur, was Du mit „Oldest“ meinst ? Für mich ist das der „latest“, also der Ordner der beim letzten Update entstanden ist.
    Ich habe auch festgestellt, daß mir als Oldest installed Exchange Build is: 15.1.2308.8 angezeigt wird, aber es die 15.1.2308.20 gibt.
    Zwischen den beiden liegt noch die .14.
    Gibt es da ne Erklärung ?
    Tx,
    Gruß
    Volker

    Reply
    • Es wird unter allen bei dir in der Org installierten Exchangeservern die „älteste“ angezeigt.
      Name : EX16
      Edition : Standard
      AdminDisplayVersion : Version 15.1 (Build 2308.8)

      Name : EX19
      Edition : Standard
      AdminDisplayVersion : Version 15.2 (Build 986.5)

      Ergibt im Skript dann:
      Oldest installed Exchange Build is: 15.1.2308.8

      Reply
      • Hallo Norbert,
        ich habe 3 EXCH2016. Wenn ich die abfrage erhalte ich
        Enterprise Version 15.1 (Build 2308.8)
        Enterprise Version 15.1 (Build 2308.8)
        Enterprise Version 15.1 (Build 2308.8)

        Also alle auf gleichem Build und für mich das „jüngste“ und nicht das älteste.
        Welchen Standpunkt soll ich einnehmen, damit ich das verstehe ;) ?

        Reply
        • Ganz einfach. Die latest ist vollkommen egal, weil du ja die „älteste“ berücksichtigen musst. Also aktualisier beim nächsten mal nur einen oder zwei deiner Server und schon wird’s klar.

  10. Hallo,

    vielen Dank für das Script. Soweit funktioniert es bei uns. Jedoch haben ich zwei Phänomene.

    1. Laut Script ist unsere Exchange-Version 15.2.986.5, in Verzeichnissen liegen aber bereits Ordner für .9 und .14 ab, selbe Ordnergröße wie .5, welches ist nun die wahre „latest Version“?

    2. Es bleiben nach dem Durchlauf trotzdem noch diverse Verzeichnisse übrig, z. B. 15.2.858.10, das Script mehrmals durchlaufen bringt nix, diese Verzeichnisse werden nicht erkannt.

    Beide oben aufgeführten Phänomene treten bei beiden Exchange 2019 Servern auf.

    Eine Idee?

    Reply
  11. Vielen Dank!
    Hier verbleiben aber noch Versionen: 15.1.1847.10 / 15.1.2176.12 / 15.1.2176.14 / 15.1.2308.14
    Ist das gewollt so?
    Grüsse Stefan

    Reply
  12. Oha, das ist ja mega! Bei der letzten Reinigung hab ich das noch manuell gemacht. Vielen Dank für Mühe und so ein tolles Script

    Reply
  13. Ich bekomme folgende Fehlermeldung in der Exchange Shell:

    [PS] C:\scripte>.\Delete-OldFolderVersions.ps1 -$DeleteOldVersions:$true
    In Zeile:1 Zeichen:33
    + .\Delete-OldFolderVersions.ps1 -$DeleteOldVersions:$true
    + ~~~~~~~~~~~~~~~~~~~
    Ungültiger Variablenverweis. Nach „:“ folgte kein Zeichen, das für einen Variablennamen gültig ist. Verwenden Sie ggf.
    „${}“, um den Namen zu begrenzen.
    + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : InvalidVariableReferenceWithDrive

    Reply
  14. Nahmd Frank,

    wieder einmal ein prima Artikel von dir!

    Leider scheine ich ein wenig zu dusslig zu sein, denn ebim Ausführen des Scripts bekomme ich Fehler:

    PS D:\Scripts> .\Delete-OldFolderVersions.ps1
    Get-ChildItem : Der Pfad „D:\Scripts\ClientAccess\ecp“ kann nicht gefunden werden, da er nicht vorhanden ist.
    In D:\Scripts\Delete-OldFolderVersions.ps1:66 Zeichen:21
    + $AllVersions += Get-ChildItem $ECPFolderPath -Directory | Where-O …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (D:\Scripts\ClientAccess\ecp:String) [Get-ChildItem], ItemNotFoundExcept
    ion
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

    Get-ChildItem : Der Pfad „D:\Scripts\ClientAccess\Owa“ kann nicht gefunden werden, da er nicht vorhanden ist.
    In D:\Scripts\Delete-OldFolderVersions.ps1:67 Zeichen:21
    + $AllVersions += Get-ChildItem $OWAFolderPath -Directory | Where-O …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (D:\Scripts\ClientAccess\Owa:String) [Get-ChildItem], ItemNotFoundExcept
    ion
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

    Get-ChildItem : Der Pfad „D:\Scripts\ClientAccess\Owa\prem“ kann nicht gefunden werden, da er nicht vorhanden ist.
    In D:\Scripts\Delete-OldFolderVersions.ps1:68 Zeichen:21
    + … $AllVersions += Get-ChildItem $OWAPremFolderPath -Directory | Where …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (D:\Scripts\ClientAccess\Owa\prem:String) [Get-ChildItem], ItemNotFoundE
    xception
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

    Old OWA / ECP folders:

    Es ist nicht möglich, eine Methode für einen Ausdruck aufzurufen, der den NULL hat.
    In D:\Scripts\Delete-OldFolderVersions.ps1:74 Zeichen:1
    + [int]$ExchangeBuild = $ExchangeServerVersion.Replace(„.“,““)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Irgendwie findet der Script den Ordner D:\Exchange nicht.

    Vielen Dank und viele Grüße

    Marcus

    Reply

Leave a Comment