<# .SYNOPSIS SharePoint Production Toolkit - Script 10 - Version URL.SharePoint Production Toolkit - Script 10 - Versioning Audit Report .PARAMETER OutputCsv Full path to output CSV. .PARAMETER SiteCollectionUrl Optional. Limit to one site collection. .PARAMETER NoPrompt Skip confirmation prompt. #> [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string]$WebAppUrl, [Parameter(Mandatory=$true)] [string]$OutputCsv, [string]$SiteCollectionUrl, [switch]$NoPrompt ) Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" Write-Host "" Write-Host "SCRIPT 10 - VERSIONING AUDIT REPORT" -ForegroundColor Cyan Write-Host "READ-ONLY. NO CHANGES ARE MADE." -ForegroundColor Green Write-Host "" # Load snap-in try { if (-not (Get-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue)) { Add-PSSnapin Microsoft.SharePoint.PowerShell } } catch { throw "Run in SharePoint Management Shell. Error: $($_.Exception.Message)" } # Output setup $outDir = Split-Path $OutputCsv -Parent if ([string]::IsNullOrWhiteSpace($outDir)) { throw "OutputCsv must be full path (e.g. C:\Temp\VersioningAudit.csv)" } if (-not (Test-Path $outDir)) { New-Item -Path $outDir -ItemType Directory -Force | Out-Null } $timestamp = (Get-Date).ToString("yyyyMMdd_HHmmss") $baseName = [System.IO.Path]::GetFileNameWithoutExtension($OutputCsv) $summaryPath = Join-Path $outDir "$baseName`_$timestamp`_Summary.csv" $logPath = Join-Path $outDir "$baseName`_$timestamp`_RunLog.txt" $errorPath = Join-Path $outDir "$baseName`_$timestamp`_Errors.csv" # Logging $log = New-Object System.Collections.Generic.List[string] $errors = New-Object System.Collections.Generic.List[object] function Log { param($msg) $line = "[{0}] {1}" -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $msg $log.Add($line) | Out-Null Write-Host $line } function Add-Error { param($scope, $msg) $errors.Add([pscustomobject]@{ Timestamp = Get-Date Scope = $scope Message = $msg }) | Out-Null } # Prompt if (-not $NoPrompt) { Write-Host "This script audits versioning settings only." -ForegroundColor Yellow if ((Read-Host "Type YES to continue") -ne "YES") { return } } # Resolve sites function Get-Sites { if ($SiteCollectionUrl) { return @(Get-SPSite -Identity $SiteCollectionUrl) } return @(Get-SPSite -WebApplication $WebAppUrl -Limit All) } # Risk model (storage + migration impact) function Get-RiskLevel { param( $EnableVersioning, $MajorLimit, $MinorLimit, $ItemCount ) if (-not $EnableVersioning) { return "Low" } if ($MajorLimit -gt 500 -or $ItemCount -gt 5000) { return "High" } if ($MajorLimit -gt 100 -or $MinorLimit -gt 20) { return "Medium" } return "Low" } function Get-Score { param($risk) switch ($risk) { "High" { return 30 } "Medium" { return 60 } "Low" { return 90 } default { return 50 } } } function Get-Recommendation { param($risk) switch ($risk) { "High" { return "Reduce version limits. Large version history increases storage and migration time." } "Medium" { return "Review version limits and confirm retention policy requirements." } "Low" { return "Versioning configuration acceptable for migration." } } } # Main execution $results = New-Object System.Collections.Generic.List[object] try { $sites = Get-Sites Log ("Resolved {0} site collection(s)." -f $sites.Count) } catch { Add-Error $WebAppUrl $_.Exception.Message throw } foreach ($site in $sites) { try { Log ("Scanning site collection: {0}" -f $site.Url) foreach ($web in $site.AllWebs) { try { foreach ($list in $web.Lists) { try { $enableVersioning = $list.EnableVersioning $enableMinor = $list.EnableMinorVersions $majorLimit = $list.MajorVersionLimit $minorLimit = $list.MajorWithMinorVersionsLimit $enableApproval = $list.EnableModeration $draftVisibility = $list.DraftVersionVisibility $itemCount = $list.ItemCount $risk = Get-RiskLevel $enableVersioning $majorLimit $minorLimit $itemCount $results.Add([pscustomobject]@{ SiteCollectionUrl = $site.Url WebUrl = $web.Url ListTitle = $list.Title ListType = $list.BaseType ItemCount = $itemCount EnableVersioning = $enableVersioning EnableMinor = $enableMinor MajorLimit = $majorLimit MinorLimit = $minorLimit ContentApproval = $enableApproval DraftVisibility = $draftVisibility RiskLevel = $risk Score = Get-Score $risk Category = "VersioningAudit" ActionRecommendation = Get-Recommendation $risk }) | Out-Null } catch { Add-Error $web.Url $_.Exception.Message } } } finally { $web.Dispose() } } $site.Dispose() } catch { Add-Error $site.Url $_.Exception.Message } } # Export detail $results | Export-Csv $OutputCsv -NoTypeInformation -Encoding UTF8 # Export summary $results | Group-Object RiskLevel | ForEach-Object { [pscustomobject]@{ RiskLevel = $_.Name Count = $_.Count } } | Export-Csv $summaryPath -NoTypeInformation -Encoding UTF8 # Logs $log | Set-Content $logPath if ($errors.Count -gt 0) { $errors | Export-Csv $errorPath -NoTypeInformation Write-Host "ERROR REPORT: $errorPath" -ForegroundColor Yellow } Write-Host "" Write-Host "DETAIL REPORT: $OutputCsv" -ForegroundColor Green Write-Host "SUMMARY REPORT: $summaryPath" -ForegroundColor Green Write-Host "RUN LOG: $logPath" -ForegroundColor Green Write-Host "Complete." -ForegroundColor Green .DESCRIPTION READ-ONLY. Audits versioning settings across SharePoint lists and libraries. Captures: - Versioning enabled - Major version limits - Minor (draft) versions - Approval settings - Checkout requirements Used for: - Migration planning - Storage optimization - Governance reviews .PARAMETER WebAppUrl