Skip to content

Instantly share code, notes, and snippets.

@AlexanderHolmeset
Last active February 13, 2025 09:46
Show Gist options
  • Save AlexanderHolmeset/ae49e5a1d179a309d9671f2f80d6d51c to your computer and use it in GitHub Desktop.
Save AlexanderHolmeset/ae49e5a1d179a309d9671f2f80d6d51c to your computer and use it in GitHub Desktop.
# Parameters for the app registration
$ClientId = "xxxxx"
$TenantId = "xxxxx"
$ClientSecret = "xxxxx"
$NumberOfMajorVersionsToKeep = 20
$TotalSizeAllVersions = 0
$TotalSizeReducedVersions = 0
# Convert the Client Secret to a SecureString
$SecureClientSecret = ConvertTo-SecureString -String $ClientSecret -AsPlainText -Force
# Create a PSCredential object with the Client ID and Secure Client Secret
$ClientSecretCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $ClientId, $SecureClientSecret
# Connect to Microsoft Graph using the Tenant ID and Client Secret Credential
Connect-MgGraph -TenantId $TenantId -ClientSecretCredential $ClientSecretCredential
# Initialize the output array
$OutputData = @()
function Get-AllDriveItems {
param (
[Parameter(Mandatory)]
[string]$DriveId,
[Parameter()]
[string]$ParentId,
[Parameter()]
[string]$CurrentPath = ""
)
$Items = @()
if ($ParentId) {
Write-Host "Processing folder with ParentId: $ParentId" -ForegroundColor Cyan
try {
$ParentItem = Get-MgDriveItem -DriveId $DriveId -DriveItemId $ParentId -ExpandProperty 'children' -ErrorAction Stop
$DriveItems = $ParentItem.Children
if($DriveItems) {
Write-Host "Found $($DriveItems.Count) child items in folder '$($ParentItem.Name)' (ParentId: $ParentId)" -ForegroundColor Green
} else {
Write-Host "No child items found in folder '$($ParentItem.Name)' (ParentId: $ParentId)" -ForegroundColor Yellow
}
} catch {
Write-Warning "Failed to get children for item ID '$ParentId'. Error: $_"
return $Items
}
} else {
Write-Host "Processing root folder" -ForegroundColor Cyan
try {
$RootItem = Get-MgDriveRoot -DriveId $DriveId -ExpandProperty 'children' -ErrorAction Stop
$DriveItems = $RootItem.Children
if($DriveItems) {
Write-Host "Found $($DriveItems.Count) items in root folder" -ForegroundColor Green
} else {
Write-Host "No items found in root folder" -ForegroundColor Yellow
}
} catch {
Write-Error "Failed to get root item and its children. Error: $_"
return $Items
}
}
if (-not $DriveItems) {
Write-Verbose "No items found at this level."
return $Items
}
foreach ($Item in $DriveItems) {
# Update the file path
if ($CurrentPath -eq "") {
$ItemPath = "/$($Item.Name)"
} else {
$ItemPath = "$CurrentPath/$($Item.Name)"
}
# Add the ItemPath property to the item
$Item | Add-Member -NotePropertyName 'ItemPath' -NotePropertyValue $ItemPath
$Items += $Item
Write-Host "Found item: $($Item.Name) (Id: $($Item.Id))" -ForegroundColor Green
if ($Item.Folder) {
Write-Host "Recursing into folder: $($Item.Name) (Id: $($Item.Id))" -ForegroundColor Cyan
if ($Item.Id) {
$Items += Get-AllDriveItems -DriveId $DriveId -ParentId $Item.Id -CurrentPath $ItemPath
} else {
Write-Warning "Item '$($Item.Name)' has a null ID and cannot be processed."
}
}
}
return $Items
}
# Now, process all SharePoint sites and their document libraries
Write-Host "Starting to process all SharePoint sites and their document libraries..." -ForegroundColor Magenta
try {
# Retrieve all SharePoint sites
$sites = Get-MgSite -All | Where-Object { $_.WebUrl -notlike "*personal*" }
} catch {
Write-Error "Failed to retrieve SharePoint sites. Error: $_"
exit
}
foreach ($site in $sites) {
try {
Write-Host "Processing site: $($site.DisplayName) <$($site.WebUrl)>" -ForegroundColor Magenta
# Get all document libraries (drives) in the site
$drives = Get-MgSiteDrive -SiteId $site.Id -ErrorAction Stop
foreach ($drive in $drives) {
Write-Host "Processing document library: $($drive.Name)" -ForegroundColor Cyan
$driveId = $drive.Id
# Get all items in the document library starting from the root
$AllItems = Get-AllDriveItems -DriveId $driveId
Write-Host "Total items retrieved in document library '$($drive.Name)': $($AllItems.Count)" -ForegroundColor Green
foreach ($Item in $AllItems) {
Write-Host "Processing item: $($Item.Name) (Id: $($Item.Id))" -ForegroundColor Gray
# Check if item is a file
if ($Item.File) {
try {
# Get versions for the item
$Versions = @()
$Versions = Get-MgDriveItemVersion -DriveId $driveId -DriveItemId $Item.Id -All -ErrorAction Stop
} catch {
Write-Warning "Failed to get versions for item '$($Item.Name)'. Error: $_"
continue
}
if (!$Versions) {
Write-Host "No versions found for item '$($Item.Name)'" -ForegroundColor Yellow
$MajorVersionCount = 0
$MinorVersionCount = 0
} else {
Write-Host "Found $($Versions.Count) versions for item '$($Item.Name)'" -ForegroundColor Green
$MajorVersionCount = 0
$MinorVersionCount = 0
$TotalVersionSize = 0
$LastversionSize = 0
$LastversionSize = ($Versions | Sort-Object -Descending -Property TotalSizeReduced)[0].Size
If($Versions){
foreach ($Version in $Versions) {
$TotalVersionSize += $Version.Size
if ($Version.id -like "*.0") {
$MajorVersionCount++
}
else {
$MinorVersionCount++
}
}
}
$TotalSizeReduced = 0
$ReducedMajorVersionCount = 0
$ReducedMinorVersionCount = 0
$ReducedMajorVersions = $Versions | Where-Object {$_.id -like "*.0"} | Sort-Object -Property LastModifiedDateTime -Descending | Select-Object -First $NumberOfMajorVersionsToKeep
foreach ($ReducedMajorVersion in $ReducedMajorVersions){
$VersionNumber = @()
$VersionNumber = ($ReducedMajorVersion.id).split(".")[0]
$Versions = $Versions | Where-Object {$_.id -like "$VersionNumber.*"}
foreach ($Version in $Versions) {
$TotalSizeReduced += $Version.Size
if ($Version.id -like "*.0") {
$ReducedMajorVersionCount++
}
else {
$ReducedMinorVersionCount++
}
}
}
# Create a custom object with the desired properties
$OutputObject = [PSCustomObject]@{
SiteUrl = $site.WebUrl
SiteName = $site.DisplayName
DocumentLibrary = $drive.Name
ItemName = $Item.Name
ItemUrl = $Item.WebUrl
FilePath = $Item.ItemPath
LastVersionSizeMB = $LastversionSize/1MB
TotalSizeMB = $TotalVersionSize/1MB
TotalSizeReducedMB = $TotalSizeReduced/1MB
MajorVersionCount = $MajorVersionCount
MinorVersionCount = $MinorVersionCount
ReducedMajorVersionCount = $ReducedMajorVersionCount
ReducedMinorVersionCount = $ReducedMinorVersionCount
}
$TotalSizeAllVersions += $TotalVersionSize
$TotalSizeReducedVersions += $TotalSizeReduced
# Add the object to the output array
$OutputData += $OutputObject
}
}
}
}
} catch {
Write-Warning "Failed to process site $($site.DisplayName). Error: $_"
continue
}
}
# Output or process the collected data as needed
# For example, output to console
#$OutputData
"Before: " + $TotalSizeAllVersions/1GB
"After: " + $TotalSizeReducedVersions/1GB
# Optionally, export to CSV
# $OutputData | Export-Csv -Path 'C:\Path\To\Output.csv' -NoTypeInformation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment