Entra / Microsoft 365 · SharePoint & OneDrive
Report deleted odsp documents
A script to report deletion activity for SharePoint Online and OneDrive for Business documents based on information in the Office 365 audit log.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Connect-ExchangeOnline -ShowBanner:$false
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
param([int] $LookbackDays = 90,[string] $StartDate = (Get-Date).AddDays(-$LookbackDays); $EndDate = (Get-Date),[string] $EndDate = (Get-Date))$Operations = "FileDeleted, FileDeletedFirstStageRecycleBin, FileDeletedSecondStageRecycleBin, FileRecycled"$FirstStageDeletions = 0; $SecondStageDeletions = 0; $UserDeletions = 0$OutputFile = "c:\temp\ODSPFileDeletions.CSV"# Find out what the OneDrive base URL is for the tenant$ServiceDomain = (Get-AcceptedDomain) | Where-Object {$_.Default -eq $True} | Select-Object -ExpandProperty Name$OneDriveDomain = ("https://{0}-my.sharepoint.com/personal/" -f $ServiceDomain.Split(".")[0])$Report = [System.Collections.Generic.List[Object]]::new() # Create output fileClear-Host; Write-Host "Searching Office 365 Audit Records to find deletion records for SharePoint and OneDrive documents"[array]$Records = Search-UnifiedAuditLog -Operations $Operations -StartDate $StartDate `-EndDate $EndDate -ResultSize 5000 -Formatted -SessionCommand ReturnLargeSetIf (!($Records)) {Write-Host "No audit records for ODSP deletions found."Break}# Remove any duplicates and sort by date$Records = $Records | Sort-Object Identity -Unique | Sort-Object { $_.CreationDate -as [datetime]} -DescendingWrite-Host "Processing" $Records.Count "ODSP file deletion records..."# Scan each audit record to extract informationForEach ($Rec in $Records) {$AuditData = ConvertFrom-Json $Rec.AuditdataSwitch ($AuditData.Operation) {"FileDeleted" { # Old Normal deletion$Reason = "Moved document to site recycle bin"$UserDeletions++}"FileRecycled" { # New Normal deletion$Reason = "Moved document to site recycle bin"$UserDeletions++}"FileDeletedFirstStageRecycleBin" { # Deletion from the first stage recycle bin$Reason = "Deleted document from first stage recycle bin"$FirstStageDeletions++}"FileDeletedSecondStageRecycleBin" { # Deletion from the second stage recycle bin$Reason = "Deleted document from second stage recycle bin"$SecondStageDeletions++}} #End switchSwitch ($AuditData.UserType) {"Regular" { # Normal user$DeletedBy = "User"If ($AuditData.UserId -eq "SHAREPOINT\System") { $DeletedBy = "SharePoint System Account" }}"CustomPolicy" { #Retention policy$DeletedBy = "Retention policy"}} #End SwitchIf ([string]::IsNullOrWhiteSpace($AuditData.UserAgent)) {$UserAgent = "Background process"} Else {$UserAgent = $AuditData.UserAgent}$Workload = "SharePoint Online"If ($AuditData.SiteUrl -match "my.sharepoint.com") { $Workload = "OneDrive for Business"}# Handle situation where it's a Teams meeting recording that expiresIf ($AuditData.SourceFileName) {$SiteURL = $AuditData.SiteURL$Folder = $AuditData.SourceRelativeURL$FileName = $AuditData.SourceFileName} Elseif ($Rec.UserIds -ne "SHAREPOINT\system") {$OneDriveUser = $Rec.Userids.Replace(".", "_")$OneDriveUser = $Rec.UserIds.Replace("@","-")$OneDriveURL = $OneDriveDomain + $OneDriveUser$AdjustedUrl = $OneDriveUrl + "/personal/" + $OneDriveUser + "/Documents/Recordings/"$FileName = $AuditData.ObjectId.SubString($AdjustedUrl.Length, $AuditData.ObjectId.Length - $AdjustedUrl.Length)$SiteUrl = $OneDriveURL$Folder = "/Recordings/"$FileName = $FileName}$ReportLine = [PSCustomObject] @{TimeStamp = Get-Date($AuditData.CreationTime) -format g"Deleted by" = $DeletedByUser = $AuditData.UserIdSite = $SiteURL"Folder" = $Folder"File name" = $FileNameWorkload = $WorkloadReason = $ReasonAction = $AuditData.OperationClient = $UserAgent}$Report.Add($ReportLine)}Clear-HostWrite-Host ("All done - ODSP Deletions in the period {0} to {1}" -f $StartDate, $EndDate)Write-Host ""Write-Host "Deletions from site: " $UserDeletionsWrite-Host "Deletions from first stage recycle bin: " $FirstStageDeletionsWrite-Host "Deletions from second stage recycle bin: " $SecondStageDeletionsWrite-Host "----------------------------------------------------------------"Write-Host ""Write-Host "CSV file containing records is available in" $OutputFile$Report | Sort-Object Reason, {$_.TimeStamp -as [datetime]} | Select-Object Timestamp, "Deleted By", Reason, User, "File Name", Site, Workload | Out-GridView$Report | Sort-Object Reason, {$_.TimeStamp -as [datetime]} | Export-CSV -NoTypeInformation $OutputFile
Parameters
ParameterDefaultNotes
-LookbackDays90Number of days back to search the unified audit log.-StartDate(Get-Date).AddDays(-90); $EndDate = (Get-Date)Start of the reporting window.-EndDate(Get-Date)End of the reporting window.Attribution
Author
Office365itpros