> For the complete documentation index, see [llms.txt](https://docs.stoik.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.stoik.io/help/help-de/email-security/microsoft-365/purview-script.md).

# Purview-Skript

Die automatisierte Version von [Purview-Aktivierungsfehler](/help/help-de/email-security/microsoft-365/purview-errors.md). Es verbindet sich mit Exchange Online, erzwingt ein Deaktivieren und anschließendes erneutes Aktivieren der Audit-Protokoll-Erfassung und bestätigt das Ergebnis. Wenn der Mandant dehydriert ist, führt es `Enable-OrganizationCustomization`, wartet, bis es abgeschlossen ist, und aktiviert dann die Audit-Protokollierung erneut. Wenn die Aktivierung tatsächlich verweigert wird, gibt es eine Diagnose aus (Kontorollen, Mandantenhydration, Lizenz- und Abostatus).

## Voraussetzungen

* **Windows PowerShell** oder **Azure Cloud Shell** (PowerShell-Modus). Das Skript verweigert die Ausführung unter macOS/Linux, wo das Exchange Online-Modul bei Schreibvorgängen fehlschlägt.
* Ein Mandanten-Administratorkonto.

{% hint style="info" %}
Keine Windows-Maschine? Wenn der Mandant ein aktives Azure-Abonnement hat, führen Sie es von [Azure Cloud Shell](https://shell.azure.com) im PowerShell-Modus aus: Laden Sie das Skript hoch und führen Sie es ohne `-AdminUpn`. Cloud Shell verwendet Ihre Sitzung erneut, daher gibt es keine Anmeldeaufforderung. Purview selbst erfordert kein Azure-Abonnement.
{% endhint %}

## Skript ausführen

{% stepper %}
{% step %}

### Skript kopieren

Kopieren Sie die [Skript](#script) mit der Kopfschaltfläche oben rechts im Codeblock und speichern Sie es als `Repair-PurviewAuditLogging.ps1`.
{% endstep %}

{% step %}

### Skriptausführung zulassen

Führen Sie dies in PowerShell einmal pro Fenster aus (nur für die Sitzung, nichts Dauerhaftes):

```powershell
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
```

{% endstep %}

{% step %}

### Führen Sie es mit dem Administratorkonto aus

Ersetzen Sie `<admin@clientdomain.com>` mit einem Mandantenadministrator. Ein Browser-Anmeldefenster öffnet sich; das Skript erledigt den Rest.

```powershell
cd C:\path\to\the\folder
.\Repair-PurviewAuditLogging.ps1 -AdminUpn <admin@clientdomain.com>
```

{% endstep %}

{% step %}

### Später überprüfen

`Falsch` direkt nach dem Ausführen ist **normal**: Microsoft wendet es innerhalb weniger Minuten an (bis zu etwa 60 Min.). Stellen Sie die Verbindung erneut her, um zu prüfen:

```powershell
Connect-ExchangeOnline -UserPrincipalName <admin@clientdomain.com> -ShowBanner:$false
Get-AdminAuditLogConfig | Format-List UnifiedAuditLogIngestionEnabled
```

`Wahr` bedeutet, dass es abgeschlossen ist.
{% endstep %}
{% endstepper %}

## Problembehandlung

Das Skript führt eine Diagnose aus und teilt Ihnen mit, in welchem Fall Sie sich befinden. Senden Sie die `.log` Datei, die es erstellt hat, an <protect@stoik.io>.

* **Dehydrierter Mandant**: wird automatisch behandelt. Das Skript führt `Enable-OrganizationCustomization`, wartet auf die Hydrierung und aktiviert dann die Audit-Protokollierung erneut.
* **403 Forbidden / verweigert**: eine tatsächliche Ablehnung. Dem Konto fehlt die richtige Rolle (die **Audit-Protokolle** Rolle, die über Organization Management oder Compliance Management gewährt wird), oder der Mandant hat keine Lizenz, die Exchange Online enthält.
* **Serverseitiger Fehler**: ein vorübergehendes „Versuchen Sie es später erneut“ von Microsoft. Das Skript versucht es bereits erneut; wenn das Problem bestehen bleibt, führen Sie es einige Minuten später erneut aus.

## Skript

{% code title="Repair-PurviewAuditLogging.ps1" lineNumbers="true" %}

```powershell
<#
.SYNOPSIS
    Reparieren Sie das einheitliche Audit-Logging von Microsoft Purview, indem Sie ein Deaktivieren und anschließendes erneutes Aktivieren erzwingen.

.DESCRIPTION
    VORAUSSETZUNG: Führen Sie dies in Windows PowerShell (5.1 oder 7+) ODER in Azure Cloud Shell aus.
    Das Skript verweigert die Ausführung an jedem anderen Ort (macOS / Desktop-Linux) - diese Umgebungen
    stoßen auf Eigenheiten des Exchange Online-Moduls und werden nicht unterstützt.

      - Windows      -> übergeben Sie -AdminUpn (oder lassen Sie es für eine interaktive Anmeldung weg).
      - Cloud Shell  -> Anmeldung erfolgt automatisch (das EXO-Modul verwendet Ihre Cloud Shell-Identität erneut).
                        Verwenden Sie -Device nur, wenn Sie ausdrücklich eine Anmeldung per Gerätecode wünschen.

    Selbst wenn die Audit-Protokollierung bereits als aktiviert angezeigt wird, kann das Purview-Portal bei
    seinem Fehler hängen bleiben. Das Erzwingen eines Deaktivierens und anschließenden erneuten Aktivierens behebt das.

    Das erneute Aktivieren erfolgt asynchron: Microsoft kann bis zu ~60 Minuten benötigen, um dies anzuzeigen, sodass eine
    frische Abfrage direkt nach einem erfolgreichen Aufruf immer noch False anzeigen kann. Das ist normal.

    Wenn die Aktivierung tatsächlich verweigert wird, führt das Skript eine Diagnose aus: verbundenes Konto &
    Rollen, Hydrationsstatus des Mandanten, Alter des Mandanten und Abonnement-/Lizenzstatus (die letzten beiden
    über Microsoft Graph, wenn verfügbar) - um auf die eigentliche Ursache hinzuweisen (Berechtigungen, Lizenzierung,
    oder ein zu neuer Mandant).

    Eine mit Zeitstempel versehene .log-Datei wird im aktuellen Ordner geschrieben.

.PARAMETER AdminUpn
    Admin-UPN (z. B. admin@clientdomain.com). Unter Windows optional (interaktive Anmeldung, wenn weggelassen).

.PARAMETER Device
    Erzwingt die Anmeldung per Gerätecode. Optional - Cloud Shell meldet sich ohne dies automatisch an.

.EXAMPLE
    .\Repair-PurviewAuditLogging.ps1 -AdminUpn admin@clientdomain.com
#>

[CmdletBinding()]
param(
    [string]$AdminUpn,
    [switch]$Device
)

$ErrorActionPreference = 'Stop'
$SupportEmail = 'protect@stoik.io'

# Geduld für die vorübergehenden „Versuchen Sie es später erneut“-Fehler von Microsoft.
$RetryCount   = 8
$RetryWaitSec = 30   # 8 x 30 s = bis zu ~4 Min. pro Umschaltung

# --- Konsolen-Hilfsfunktionen ------------------------------------------------
function Write-Step { param($m) Write-Host "`n==> $m" -ForegroundColor Cyan }
function Write-Ok   { param($m) Write-Host "    [OK]   $m" -ForegroundColor Green }
function Write-Info { param($m) Write-Host "    [..]   $m" -ForegroundColor Gray }
function Write-Warn2{ param($m) Write-Host "    [WARN] $m" -ForegroundColor Yellow }
function Write-Err  { param($m) Write-Host "    [FAIL] $m" -ForegroundColor Red }

# --- Umgebungsdetektion + Voraussetzungsgate --------------------------------
# Cloud Shell setzt eine davon; Windows PowerShell 5.1 hat kein $IsWindows, daher
# akzeptieren wir auch die Desktop-Edition.
$IsCloudShell = [bool]$env:ACC_CLOUD `
                -or ($env:POWERSHELL_DISTRIBUTION_CHANNEL -like '*CloudShell*') `
                -or ($env:AZUREPS_HOST_ENVIRONMENT -like '*cloud-shell*')
$OnWindows    = $IsWindows -or ($PSVersionTable.PSEdition -eq 'Desktop')

$exoVersion = (Get-Module -ListAvailable -Name ExchangeOnlineManagement |
               Sort-Object Version -Descending | Select-Object -First 1).Version

Write-Step "Umgebung"
Write-Host "    OS / platform : $([System.Environment]::OSVersion.VersionString)"
Write-Host "    PowerShell    : $($PSVersionTable.PSVersion) ($($PSVersionTable.PSEdition))"
Write-Host "    Context       : $(if ($IsCloudShell) {'Azure Cloud Shell'} elseif ($OnWindows) {'Windows'} else {'nicht unterstützt'})"
Write-Host "    EXO module    : $(if ($exoVersion) {$exoVersion} else {'nicht installiert'})"

if (-not ($OnWindows -or $IsCloudShell)) {
    Nicht unterstützte Umgebung.
    Write-Host "    Dieses Skript läuft nur in Windows PowerShell oder in Azure Cloud Shell." -ForegroundColor Yellow
    Write-Host "    Führen Sie es erneut von einem Windows-Computer oder von https://shell.azure.com (PowerShell) aus." -ForegroundColor Yellow
    exit 2
}

# --- Protokollierung --------------------------------------------------------
$timestamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$LogFile   = Join-Path (Get-Location) "purview-repair-$timestamp.log"
Start-Transcript -Path $LogFile -Append | Out-Null

# Text in eine Begleitdatei schreiben, ohne jemals eine Ausnahme auszulösen (die .log-Datei wird vom Transkript verwaltet).
function Save-ErrorDetail {
    param($Text)
    if ([string]::IsNullOrWhiteSpace($Text)) { return $null }
    try {
        $f = [System.IO.Path]::ChangeExtension($LogFile, 'error.txt')
        "VOLLSTÄNDIGE FEHLERDETAILS (für den Support)`n$Text" | Out-File -FilePath $f -ErrorAction Stop
        return $f
    } catch { return $null }
}

$connected = $false

# Führt Set-AdminAuditLogConfig einmal aus und klassifiziert das Ergebnis. EXO-REST-Cmdlets
# beachten try/catch nicht immer, daher prüfen wir -ErrorVariable.
function Set-AuditIngestionOnce {
    param([bool]$Value)
    $ErrorActionPreference = 'Continue'
    # Die rohe Warnung „...bis zu 60 Minuten zur Anwendung“ in der Konsole ausblenden (wir erfassen sie dennoch
    # über -WarningVariable und geben unser eigenes [OK] aus). Dies ist eine Präferenz, keine Befehls-
    # dekoration oder Umleitung eines Streams.
    $WarningPreference = 'SilentlyContinue'
    $err = $null; $warn = $null
    # WICHTIG: genau wie einen von Hand eingegebenen Befehl aufrufen. Das Dekorieren des Aufrufs mit
    # -WarningAction SilentlyContinue / 2>$null / | Out-Null führt dazu, dass EXO fälschlicherweise ein (403)
    # innerhalb eines Skripts zurückgibt, während der nackte Befehl erfolgreich ist. -ErrorVariable / -WarningVariable
    # erfassen nur die Streams; sie ändern nicht, wie das Cmdlet mit dem Server kommuniziert.
    $null = Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $Value `
        -ErrorVariable err -WarningVariable warn
    $errText  = ($err  | ForEach-Object { $_.ToString() }) -join ' '
    $warnText = ($warn | ForEach-Object { $_.ToString() }) -join ' '
    if ($errText) { $script:LastFullError = $errText }

    $dehydrated = ($errText -match 'Enable-OrganizationCustomization')
    $serverSide = ($errText -match 'server side error|try again after some time')
    $forbidden  = (-not $serverSide) -and ($errText -match '403|Forbidden|Interdit|Access is denied|not authorized|insufficient')

    if     ($dehydrated) { $short = 'Mandant ist dehydriert (benötigt Enable-OrganizationCustomization).' }
    elseif ($forbidden)  { $short = '403 Forbidden - Problem mit Berechtigungen / Rolle / Lizenzierung.' }
    elseif ($serverSide) { $short = "Microsoft ist beschäftigt (serverseitiger Fehler, 'Versuchen Sie es später erneut')." }
    elseif ($errText)    { $short = ($errText -split "`n")[0] }
    else                 { $short = '' }

    [pscustomobject]@{
        Ok = [string]::IsNullOrWhiteSpace($errText); Warning = $warnText; Error = $errText
        Short = $short; Dehydrated = $dehydrated; Forbidden = $forbidden; ServerSide = $serverSide
    }
}

# Die Einstellung umschalten und nur bei vorübergehenden Fehlern erneut versuchen.
function Invoke-AuditToggle {
    param([bool]$Value, [string]$Label)
    $r = $null
    for ($i = 1; $i -le $RetryCount; $i++) {
        $r = Set-AuditIngestionOnce $Value
        if ($r.Ok)         { Write-Ok "$Label wurde von Microsoft akzeptiert."; return $r }
        if ($r.Dehydrated) { return $r }                       # caller hydrates then retries
        if ($r.Forbidden)  { Write-Warn2 "$Label abgelehnt (Berechtigungen / Rolle / Lizenzierung) - kein erneuter Versuch."; return $r }

        Write-Warn2 "$Label fehlgeschlagen (Versuch $i/$RetryCount): $($r.Short)"
        if ($i -lt $RetryCount) {
            Write-Info "Wiederhole $Label in ${RetryWaitSec} s."
            Start-Sleep -Seconds $RetryWaitSec
        }
    }
    return $r
}

# Manuelle Checkliste, die angezeigt wird, wenn Graph Abonnement / Lizenzierung / Mandantenalter nicht automatisch prüfen kann.
function Write-ManualChecklist {
    Write-Info "Prüfen Sie manuell im Microsoft 365 Admin Center (admin.microsoft.com):"
    Write-Info "  - Abrechnung > Ihre Produkte : Das Abonnement ist Aktiv (nicht ausgesetzt/abgelaufen)."
    Write-Info "  - Eine Lizenz, die Exchange Online enthält, ist zugewiesen (die meisten M365/O365-Pläne)."
    Write-Info "  - Einrichtungsdatum : Bei Mandanten, die in den letzten ~72 Stunden erstellt wurden, ist die Audit-Bereitstellung möglicherweise noch nicht bereit."
}

# Vollständige Diagnose, wenn die Aktivierung tatsächlich verweigert wird.
function Invoke-FailureDiagnostic {
    param($ErrInfo)
    Write-Step "Diagnose - warum wurde die Aktivierung verweigert?"
    if ($ErrInfo -and $ErrInfo.Short) { Write-Info "Gemeldeter Fehler : $($ErrInfo.Short)" }

    # Verbundene Identität
    $upn = $null
    try {
        $ci  = Get-ConnectionInformation -ErrorAction Stop | Select-Object -First 1
        $upn = $ci.UserPrincipalName
        Write-Info "Verbunden als   : $upn"
        Write-Info "Mandanten-ID    : $($ci.TenantId)"
    } catch { Write-Info "Verbindungsinformationen konnten nicht gelesen werden." }

    # Mandanten-/Organisationskonfiguration
    try {
        $org = Get-OrganizationConfig -ErrorAction Stop
        Write-Info "Organisation   : $($org.DisplayName) [$($org.Name)]"
        Write-Info "IsDehydrated   : $($org.IsDehydrated)$(if ($org.IsDehydrated) {'  <- run Enable-OrganizationCustomization'})"
    } catch { Write-Info "Get-OrganizationConfig konnte nicht gelesen werden." }

    # Berechtigungen: Besitzt das Konto eine Rolle, mit der die Audit-Konfiguration festgelegt werden kann?
    if ($upn) {
        try {
            $roles = Get-ManagementRoleAssignment -RoleAssignee $upn -Delegating:$false -ErrorAction Stop |
                     Select-Object -ExpandProperty Role -Unique
            Write-Info "Rollen          : $([string]::Join(', ', $roles))"
            if ($roles -contains 'Audit Logs' -or $roles -contains 'Organization Configuration') {
                Write-Ok "Das Konto besitzt eine Rolle, die die Audit-Konfiguration erlaubt."
            } else {
                Write-Warn2 "Dem Konto fehlen 'Organization Configuration' / 'Audit Logs'."
                Write-Warn2 "=> Fügen Sie es der Rollengruppe 'Organization Management' hinzu (Exchange Admin Center)."
            }
        } catch { Write-Info "Rollen konnten nicht aufgelistet werden ($($_.Exception.Message))." }
    }

    # Abonnement-/Lizenzierung-/Mandantenalter über Microsoft Graph (nach Möglichkeit, nicht fatal).
    if (Get-Command Get-MgOrganization -ErrorAction SilentlyContinue) {
        try {
            if (-not (Get-MgContext -ErrorAction SilentlyContinue)) {
                Write-Info "Verbinde mit Microsoft Graph (nur Lesen) für Abonnement-/Lizenz-/Altersprüfungen..."
                Connect-MgGraph -Scopes 'Organization.Read.All' -NoWelcome -ErrorAction Stop
            }
            $o = Get-MgOrganization -ErrorAction Stop | Select-Object -First 1
            if ($o.CreatedDateTime) {
                $age = (New-TimeSpan -Start $o.CreatedDateTime -End (Get-Date)).Days
                Write-Info "Mandant erstellt : $($o.CreatedDateTime) (~$age days ago)"
                if ($age -lt 3) { Write-Warn2 "Der Mandant ist sehr neu (<3 Tage) - die Audit-Bereitstellung ist möglicherweise noch nicht fertig. Später erneut versuchen." }
            }
            foreach ($s in (Get-MgSubscribedSku -ErrorAction Stop)) {
                Write-Info "Lizenz        : $($s.SkuPartNumber)  status=$($s.CapabilityStatus)  seats=$($s.PrepaidUnits.Enabled)"
                if ($s.CapabilityStatus -in 'Suspended','Deleted') {
                    Write-Warn2 "Das Abonnement '$($s.SkuPartNumber)' ist $($s.CapabilityStatus) - nicht aktiv."
                }
            }
        } catch {
            Write-Info "Graph-Prüfung nicht verfügbar: $($_.Exception.Message)"
            Write-ManualChecklist
        }
    } else {
        Write-Info "Microsoft-Graph-Modul nicht installiert - Abonnement/Lizenz/Mandantenalter kann nicht automatisch geprüft werden."
        Write-ManualChecklist
    }
}

try {
    # --- Voraussetzungen -----------------------------------------------------
    Write-Step "Überprüfe Voraussetzungen"
    if (-not $exoVersion) {
        Write-Warn2 "ExchangeOnlineManagement nicht gefunden. Wird für den aktuellen Benutzer installiert."
        if ($OnWindows -and $PSVersionTable.PSEdition -eq 'Desktop') {
            # Windows PowerShell 5.1 benötigt oft ausdrücklich TLS 1.2, um die PSGallery zu erreichen.
            [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
        }
        Install-Module -Name ExchangeOnlineManagement -Scope CurrentUser -Force -AllowClobber
        Write-Ok "Modul installiert."
    } else {
        Write-Ok "ExchangeOnlineManagement vorhanden ($exoVersion)."
    }
    Import-Module ExchangeOnlineManagement

    # --- Verbinden -----------------------------------------------------------
    Write-Step "Verbinden mit Exchange Online"
    # In Azure Cloud Shell verwendet das EXO-Modul die Sitzungsidentität automatisch erneut - KEIN Gerät
    # code. Erzwingen Sie den Gerätecode nur, wenn der Benutzer dies ausdrücklich mit -Device verlangt.
    $useDevice = [bool]$Device
    if ($useDevice -and $AdminUpn) {
        Write-Warn2 "Anmeldung per Gerätecode: Öffnen Sie die unten angezeigte URL und geben Sie den Code ein."
        Connect-ExchangeOnline -UserPrincipalName $AdminUpn -Device -ShowBanner:$false
    } elseif ($useDevice) {
        Write-Warn2 "Anmeldung per Gerätecode: Öffnen Sie die unten angezeigte URL und geben Sie den Code ein."
        Connect-ExchangeOnline -Device -ShowBanner:$false
    } elseif ($AdminUpn) {
        Connect-ExchangeOnline -UserPrincipalName $AdminUpn -ShowBanner:$false
    } else {
        Connect-ExchangeOnline -ShowBanner:$false
    }
    $connected = $true
    Write-Ok "Verbunden."

    # --- Diagnose -----------------------------------------------------------
    Write-Step "Aktueller Status"
    $enabled      = (Get-AdminAuditLogConfig).UnifiedAuditLogIngestionEnabled
    $isDehydrated = (Get-OrganizationConfig).IsDehydrated
    Write-Host "    UnifiedAuditLogIngestionEnabled : $enabled"
    Write-Host "    IsDehydrated                    : $isDehydrated"

    # --- Zuerst deaktivieren nur, wenn derzeit AKTIV (der Aus-/Ein-Zyklus entsperrt das Portal) -------
    if ($enabled) {
        Write-Step "Schritt 1 - Erfassung deaktivieren (um einen sauberen Aus-/Ein-Zyklus zu erzwingen)"
        $d = Invoke-AuditToggle -Value $false -Label "Disable"
        if (-not $d.Ok) { Write-Warn2 "Deaktivierung wurde nicht bestätigt ($($d.Short)) - wir fahren trotzdem mit der erneuten Aktivierung fort." }
    } else {
        Write-Info "Audit-Protokollierung ist derzeit AUS - direkt aktivieren (keine Deaktivierung nötig)."
    }

    # --- Aktivieren ---------------------------------------------------------
    Write-Step "Schritt 2 - Erfassung aktivieren"
    $e = Invoke-AuditToggle -Value $true -Label "Enable"
    if ($e.Dehydrated) {
        Write-Warn2 "Dehydrierter Mandant. Enable-OrganizationCustomization wird ausgeführt."
        try { Enable-OrganizationCustomization } catch { Write-Warn2 $_.Exception.Message }
        $h = 0
        do {
            Start-Sleep -Seconds 15
            $isDehydrated = (Get-OrganizationConfig).IsDehydrated
            $h++
            Write-Info "Warte auf Hydrierung... Versuch $h (IsDehydrated = $isDehydrated)"
        } while ($isDehydrated -and $h -lt 8)
        if ($isDehydrated) { throw "Der Mandant ist nach dem Warten immer noch dehydriert. In einigen Minuten erneut ausführen." }
        Write-Ok "Mandant hydriert."
        $e = Invoke-AuditToggle -Value $true -Label "Re-enable"
    }

    # --- Ergebnis ----------------------------------------------------------
    Write-Step "Ergebnis"
    Start-Sleep -Seconds 5
    $final = (Get-AdminAuditLogConfig).UnifiedAuditLogIngestionEnabled
    Write-Host "    UnifiedAuditLogIngestionEnabled (fresh read) : $final"

    # Die frische Abfrage ist die maßgebliche Wahrheit: Wenn sie True ist, IST die Audit-Protokollierung aktiviert, selbst wenn der
    # letzte Aktivierungsaufruf $e.Ok false hinterlassen hat (vorübergehendes 403, „Erneut versuchen“-Rauschen auf dem Fehler-Stream).
    if ($final) {
        Write-Ok "Audit-Protokollierung ist AKTIVIERT. Fertig."
    }
    elseif ($e.Ok) {
        Write-Warn2 "Die erneute Aktivierung wurde akzeptiert, wird aber immer noch als False gelesen - normal: Microsoft kann bis zu"
        Write-Host  "    ~60 Minuten benötigen, um sie anzuwenden. Prüfen Sie kurz darauf erneut mit dem folgenden Befehl." -ForegroundColor Yellow
    }
    else {
        Write-Err "Die Aktivierung wurde von Microsoft NICHT akzeptiert. Diagnose wird ausgeführt."
        Save-ErrorDetail $script:LastFullError | Out-Null
        Invoke-FailureDiagnostic $e
    }

    # --- Später überprüfen --------------------------------------------------
    Write-Step "Später überprüfen (zuerst erneut verbinden, das Skript trennt am Ende)"
    if ($AdminUpn) {
        Write-Host  "        Connect-ExchangeOnline -UserPrincipalName $AdminUpn -ShowBanner:`$false" -ForegroundColor Gray
    } else {
        Write-Host  "        Connect-ExchangeOnline -ShowBanner:`$false" -ForegroundColor Gray
    }
    Write-Host  "        Get-AdminAuditLogConfig | Format-List UnifiedAuditLogIngestionEnabled" -ForegroundColor Gray
    Write-Host  "    'True' bedeutet, dass es aktiviert ist."
}
catch {
    Write-Err "Etwas ist schiefgelaufen: $($_.Exception.Message)"
    if ($connected) { try { Invoke-FailureDiagnostic $null } catch { } }
    $errorFile = Save-ErrorDetail $script:LastFullError
    Write-Host ""
    Write-Host "    >> Wenn Sie Hilfe benötigen, senden Sie die Protokolldatei an $SupportEmail :" -ForegroundColor Yellow
    Write-Host "       $LogFile" -ForegroundColor Yellow
    if ($errorFile) { Write-Host "       $errorFile" -ForegroundColor Yellow }
}
finally {
    if ($connected) {
        Write-Step "Trennen"
        try { Disconnect-ExchangeOnline -Confirm:$false } catch { }
        Write-Ok "Getrennt."
    }
    Write-Host "`nProtokoll gespeichert unter: $LogFile" -ForegroundColor Gray
    Stop-Transcript | Out-Null
}
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.stoik.io/help/help-de/email-security/microsoft-365/purview-script.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
