Exchange: Delete old OWA/ECP data

Exchange Server leaves old data or versions of the OWA and ECP directories on the file system after almost every update. In particular, the directory "C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\Owa\prem" takes up some space on the file system after a long runtime and correspondingly many updates. Here is an example of an Exchange Server that has been running for a while:

Old file versions / data in the "prem" directory occupy 16 GB on the file system. This data is no longer used. Frank C. (msXfaq) has written an article on this topic that is well worth reading:

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

Although the "few" GB are likely to upset at least a few people, storage space could become scarce. So if a drive is threatening to fill up, it makes sense to know where you can get some breathing space. Next to the Exchange server log files you can also gain some storage space here.

Frank C. also has the following sentence in his article:

You could of course also automate the deletion of old versions using PowerShell or similar.

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

I have taken the sentence and converted it into a PowerShell script. The following PowerShell script lists all old versions in the following directories:

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

For security reasons, the script determines the oldest Exchange Server version (in environments with multiple Exchange Servers) and lists all versions of the directories that are older than the oldest Exchange Server. This ensures that the directory versions matching the build of the oldest Exchange Server remain available and are not deleted.

The script only lists the old directory versions when it is executed, but does not delete them. The data is only deleted if the parameter "-$DeleteOldVersions:$true" is specified.

Here is the script, which can be copied into a .PS1 file:

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
}
}

If you want it a little easier, I have also published the script on GitHub:

Update 07.12.2021: The script has been updated to include more older versions, the changes can be tracked on GitHub. Thank you for the 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