Entra / Microsoft 365 · Compliance & audit
Update OneDrive retention labels
Updates assigned retention labels on selected files in a user's OneDrive for Business account based on a file report.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Connect-MgGraph -Scopes Files.Read.All, RecordsManagement.Read.All, InformationProtectionPolicy.Read -NoWelcome
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
function Get-DriveItems {[CmdletBinding()]param ([Parameter()]$Drive,[Parameter()]$FolderId)# Get OneDrive items for a folder[array]$Data = Get-MgDriveItemChild -DriveId $Drive -DriveItemId $FolderId -All# Split the data into files and folders[array]$Folders = $Data | Where-Object {$_.folder.childcount -gt 0}$Global:TotalFolders = $TotalFolders + $Folders.Count[array]$Files = $Data | Where-Object {$null -ne $_.file.mimetype}ForEach ($File in $Files) {# Write-Output ("Processing file {0}" -f $File.Name)$ReplacedLabel = $false# Get retention label informationTry {$RetentionLabelInfo = $null; $RetentionLabelName = $null$RetentionlabelInfo = Get-MgDriveItemRetentionLabel -DriveId $OneDriveInfo.Id -DriveItemId $File.Id -ErrorAction StopIf ($RetentionLabelInfo.name -eq $OldRetentionLabelName) {$Status = Update-MgDriveItemRetentionLabel -DriveId $OneDriveInfo.Id -DriveItemId $File.Id -BodyParameter $NewRetentionLabelParameters -ErrorAction StopIf ($Status.Name) {Write-Host ("File {0} had the {1} label and has been assigned the {2} retention label" -f $File.Name, $OldRetentionLabelName, $NewRetentionLabelName) -ForegroundColor Yellow$ReplacedLabel = $true} Else {Write-Host ("File {0} had the {1} label, but the update to the {2} label failed" -f $File.Name, $OldRetentionLabelName, $NewRetentionLabelName) -ForegroundColor Red}}} Catch {Write-Host ("Error reading retention label data from file {0}" -f $File.Name)}If ($File.LastModifiedDateTime) {$FileLastModifiedDateTime = Get-Date $File.LastModifiedDateTime -format 'dd-MMM-yyyy HH:mm'} Else {$FileLastModifiedDateTime = $null}If ($File.CreatedDateTime) {[datetime]$FileCreated = $File.createdDateTime$AgeInDays = (New-TimeSpan $FileCreated).Days$FileCreatedDateTime = Get-Date $File.CreatedDateTime -format 'dd-MMM-yyyy HH:mm'}If ([string]::IsNullOrEmpty($RetentionLabelName)) {$RetentionLabelName = "No label"} Else {[string]$RetentionLabelName = $RetentionLabelName.Trim()}If ($ReplacedLabel -eq $true) {$ReportLine = [PSCustomObject]@{FileName = $File.NameFolder = $File.parentreference.nameAuthor = $File.createdby.user.displaynameCreated = $FileCreatedDateTimeModified = $FileLastModifiedDateTimeSize = (FormatFileSize $File.Size)DaysOld = $AgeInDays'Retention label' = $RetentionLabelInfo.name'New Retention label' = $NewRetentionLabelNameFileType = $FileTypeBytes = $File.SizeWebURL = $File.WebUrl}$ODBFiles.Add($ReportLine)}}ForEach ($Folder in $Folders) {Write-Host ("Processing folder {0} ({1} files/size {2})" -f $Folder.Name, $Folder.folder.childcount, (FormatFileSize $Folder.Size))Get-DriveItems -Drive $Drive -FolderId $Folder.Id}}function FormatFileSize {# Format File Size nicelyparam ([parameter(Mandatory = $true)]$InFileSize)If ($InFileSize -lt 1KB) { # Format the size of a document$FileSize = $InFileSize.ToString() + " B"} ElseIf ($InFileSize -lt 1MB) {$FileSize = $InFileSize / 1KB$FileSize = ("{0:n2}" -f $FileSize) + " KB"} Elseif ($InFileSize -lt 1GB) {$FileSize = $InFileSize / 1MB$FileSize = ("{0:n2}" -f $FileSize) + " MB"} Elseif ($InFileSize -ge 1GB) {$FileSize = $InFileSize / 1GB$FileSize = ("{0:n2}" -f $FileSize) + " GB"}Return $FileSize}# Connect to the Microsoft Graph with the permission to read sitesDisconnect-MgGraph | Out-Null # Make sure that we sign out of existing sessions# User must have a valid license for OneDrive for Business...Connect-MgGraph -Scopes Files.Read.All, RecordsManagement.Read.All, InformationProtectionPolicy.Read -NoWelcomeWrite-Host "Getting ready to apply replacement retention labels in a OneDrive for Business account..."# Discover if the tenant uses sensitivity labels$Account = (Get-MgContext).Account# Discover if the tenant uses retention labels[array]$RetentionLabels = Get-MgSecurityLabelRetentionLabelIf ($RetentionLabels) {$Global:RetentionLabelsAvailable = $true$RetentionLabels = $RetentionLabels | Sort-Object DisplayNameWrite-Host ("Tenant has {0} retention labels available" -f $RetentionLabels.Count) -ForegroundColor Green} Else {Write-Host "No retention labels available in the tenant. Exiting because without labels we can't switch anything" -ForegroundColor RedBreak}# List retention label display names and prompt user to select the label to find and its replacementWrite-Host "Available Retention Labels:"for ($i = 0; $i -lt $RetentionLabels.Count; $i++) {Write-Host ("[{0}] {1}" -f ($i + 1), $RetentionLabels[$i].DisplayName)}do {[int]$Selection = Read-Host "Enter the number of the retention label to replace"$IsValid = (($Selection -ge 1) -and ($Selection -le $RetentionLabels.Count))if (-not $IsValid) {Write-Host "Invalid selection. Please enter a number between 1 and $($RetentionLabels.Count)." -ForegroundColor Yellow}} until ($IsValid)[int]$OriginalSelection = $Selection$ReplaceLabel = $RetentionLabels[$Selection - 1]Write-Host ("You selected the {0} retention label" -f $ReplaceLabel.DisplayName) -ForegroundColor Greendo {[int]$Selection = Read-Host ("Now select the number of the retention label to apply to files that have the {0} label" -f $ReplaceLabel.DisplayName)$IsValid = (($Selection -ge 1) -and ($Selection -le $RetentionLabels.Count) -and ($Selection -ne $OriginalSelection))if (-not $IsValid) {Write-Host "Invalid selection. Please enter a number between 1 and $($RetentionLabels.Count)." -ForegroundColor Yellow}} until ($IsValid)$NewLabel = $RetentionLabels[$Selection - 1]Write-Host ("The {0} retention label will replace the {1} label" -f $NewLabel.DisplayName, $ReplaceLabel.DisplayName) -ForegroundColor Green# Define the hash table for the new retention label parameters$Global:NewRetentionLabelParameters = @{}$NewRetentionLabelParameters.Add("Name",$NewLabel.DisplayName)$Global:OldRetentionLabelName = $ReplaceLabel.DisplayName$Global:NewRetentionLabelName = $NewLabel.DisplayName# Find user's OneDrive for Business account[array]$OneDriveInfo = Get-MgUserDefaultDrive -UserId $AccountIf (!($OneDriveInfo)) { # Nothing foundWrite-Host ("No matching OneDrive for Business account found for {0} - exiting" -f $Account)break} Else {Write-Host ("Found OneDrive account owned by {0} to process. URL: {1}" -f $OneDriveInfo.owner.user.displayName, $OneDriveInfo.WebUrl)$Global:OneDriveName = $OneDriveInfo.name}# Create output list and CSV file$Global:ODBFiles = [System.Collections.Generic.List[Object]]::new()$CSVOutputFile = ((New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path) + ("\Relabeled OneDrive files for {0}.csv" -f $OneDriveInfo.owner.user.displayName)[datetime]$StartProcessing = Get-Date$Global:TotalFolders = 1# Get the items in the root, including child foldersWrite-Host "Fetching file information from OneDrive for Business..." -ForegroundColor YellowGet-DriveItems -Drive $OneDriveInfo.id -FolderId "root"[datetime]$EndProcessing = Get-Date$ElapsedTime = ($EndProcessing - $StartProcessing)$FilesPerMinute = [math]::Round(($ODBFiles.Count / ($ElapsedTime.TotalSeconds / 60)), 2)# Show what we've found with Out-GridView$ODBFiles | Select-Object FileName, Folder, Author, Created, Modified, Size, DaysOld, 'Retention Label', 'Sensitivity Label' | `Out-GridView -Title ("OneDrive for Business Files for {0}" -f $OneDriveInfo.owner.user.displayName)Write-Host ("A total of {0} files were reassigned with the {1} retention label" -f $ODBFiles.Count, $NewLabel.DisplayName)$ODBFiles | Select-Object FileName, Folder, Author, Created, Modified, Size, DaysOld, 'Retention Label', 'Sensitivity Label' | `Export-Csv -Path $CSVOutputFile -NoTypeInformation -Encoding UTF8Write-Host ("CSV file containing details of relabeled files available at {0}" -f $CSVOutputFile) -ForegroundColor GreenWrite-Host ("Processed {0} files in {1} folders in {2}:{3} minutes ({4} files/minute)" -f `$ODBFiles.Count, $TotalFolders, $ElapsedTime.Minutes, $ElapsedTime.Seconds, $FilesPerMinute)
Attribution
Author
Office365itpros