<# .SYNOPSIS Get-CMOneDriveUsageReport.ps1 .DESCRIPTION Lists every OneDrive (personal site) in the tenant with owner, storage used, storage quota and last content modified date, and exports it to CSV. Read-only: it changes nothing in your tenant. The site query is the one Microsoft documents for listing OneDrive URLs: Get-SPOSite -IncludePersonalSite $true -Limit all -Filter "Url -like '-my.sharepoint.com/personal/'" Provided by cloud-migrations.au as is; test before use. Read the script before you run it and try it in a test tenant first. .NOTES Requirements - SharePoint Online Management Shell: Install-Module -Name Microsoft.Online.SharePoint.PowerShell -Scope CurrentUser - SharePoint Administrator role - Windows PowerShell 5.1, or PowerShell 7 with: Import-Module Microsoft.Online.SharePoint.PowerShell -UseWindowsPowerShell Commands used (documented by Microsoft): Connect-SPOService, Get-SPOSite, Disconnect-SPOService .EXAMPLE .\Get-CMOneDriveUsageReport.ps1 -AdminUrl https://contoso-admin.sharepoint.com #> [CmdletBinding()] param( [Parameter(Mandatory = $true)][string]$AdminUrl, [string]$OutputPath = (Join-Path -Path (Get-Location) -ChildPath ('OneDriveUsageReport_{0}.csv' -f (Get-Date -Format 'yyyyMMdd_HHmm'))), [switch]$SkipConnect ) $ErrorActionPreference = 'Stop' # 1. Connect if (-not $SkipConnect) { try { Write-Host "Connecting to $AdminUrl ..." Connect-SPOService -Url $AdminUrl } catch { Write-Error "Could not connect to SharePoint: $($_.Exception.Message)" return } } # 2. List OneDrive sites try { Write-Progress -Activity 'OneDrive usage report' -Status 'Listing OneDrive sites (this can take a while in large tenants)...' -PercentComplete 10 $sites = @(Get-SPOSite -IncludePersonalSite $true -Limit all -Filter "Url -like '-my.sharepoint.com/personal/'") } catch { Write-Error "Get-SPOSite failed: $($_.Exception.Message)" return } Write-Host ("Found {0} OneDrive sites." -f $sites.Count) # 3. Shape the rows $results = New-Object System.Collections.Generic.List[object] $i = 0 foreach ($s in $sites) { $i++ if ($i % 50 -eq 0 -or $i -eq $sites.Count) { Write-Progress -Activity 'OneDrive usage report' -Status ("Processing {0} of {1}" -f $i, $sites.Count) -PercentComplete (10 + (($i / [math]::Max($sites.Count, 1)) * 90)) } $results.Add([pscustomobject][ordered]@{ Url = $s.Url Owner = $s.Owner Title = $s.Title StorageUsageCurrent = $s.StorageUsageCurrent StorageQuota = $s.StorageQuota LastContentModifiedDate = $s.LastContentModifiedDate LockState = $s.LockState }) } Write-Progress -Activity 'OneDrive usage report' -Completed # 4. Export try { $results | Sort-Object -Property StorageUsageCurrent -Descending | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8 Write-Host ("Done. {0} OneDrive sites written." -f $results.Count) Write-Host "Report saved to: $((Resolve-Path -Path $OutputPath).Path)" } catch { Write-Error "Could not write the CSV to $OutputPath : $($_.Exception.Message)" } finally { if (-not $SkipConnect) { Disconnect-SPOService } }