# Function to update a list of paths Function Update-ListOfPaths { param([System.Collections.ArrayList]$List,[string]$Path) If ( $List -inotcontains $Path ) { $List.Add($Path) | Out-Null } } # Function to expand the UserProfile environment variable as used by MSP360, and update $List Function Add-UserProfilePaths { param([System.Collections.ArrayList]$List,[string]$Path) # Get a list of all user profile directories $ProfilePath = (Get-ItemPropertyValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' -Name ProfilesDirectory) $UserProfilePaths = @() ForEach ( $userProfile in (Get-ChildItem -Path $ProfilePath | Where-Object { $_.PSIsContainer }) ) { $UserProfilePaths += ,@($userProfile.FullName) } # Iterate over each $profilePath and join it with the supplied $Path ForEach ( $profilePath in $UserProfilePaths ) { Update-ListOfPaths -List $List -Path $(Join-Path -Path $profilePath -ChildPath $($Path -split '%')[2]) } } Function Use-Path { param([System.Collections.ArrayList]$List,[string]$Path) Switch ( $Path ) { { $_ -ilike '*%UserProfile%*' } { Add-UserProfilePaths -List $List -Path $Path } { $_ -ilike '*%*%*' } { Update-ListOfPaths -List $List -Path $([System.Environment]::ExpandEnvironmentVariables($Path)) } default { Update-ListOfPaths -List $List -Path $Path } } } # Import MSP360 module Import-MSP360Module # Get all backup plans $BackupPlans = Get-MBSBackupPlan -OutputType Full # Iterate over all backup plans ForEach ( $plan in $BackupPlans ) { # Function to process each file Function ProcessFile { param([System.IO.FileInfo]$File) Switch ( $File ) { # Filter out if name matches an excluded path { $null -ne ($ExcludedPaths | Where-Object { $File.FullName.Replace('\','\\') -match $_.Replace('\','\\') }) } { Update-FilteredFiles $File } # Filter out if file size is greater than plan maximum { $File.Length -gt $plan.MaxFileSize } { Update-FilteredFiles $File } # Add item to $IncludeFiles default { $IncludedFiles.Add($item.FullName, $item.Length) | Out-Null } } } # Function to add a file to $FilteredFiles Function Update-FilteredFiles { param([System.IO.FileInfo]$File) $FilteredFiles.Add($File.FullName, $File.Length) | Out-Null } Write-Output ('Plan Name: {0}' -f ($plan.Name)) # Create array lists to store paths included in the plans [System.Collections.ArrayList]$IncludedPaths = @() [System.Collections.ArrayList]$ExcludedPaths = @() # Create array lists to keep files matching certain patterns [System.Collections.Hashtable]$FilteredFiles = @{} [System.Collections.Hashtable]$IncludedFiles = @{} # Get all included items ForEach ( $obj in $plan.Items ) { ForEach ( $path in $obj.PlanItem.Path ) { Use-Path -List $IncludedPaths -Path $path } } # Get all excluded items ForEach ( $obj in $plan.ExcludedItems ) { ForEach ( $path in $obj.PlanItem.Path ) { Use-Path -List $ExcludedPaths -Path $path } } # Process each path in $IncludedPaths ForEach ($path in $IncludedPaths ) { # Skip paths that don't exist If ( !(Test-Path $path) ) { Continue } # If $path is an individual file, process it separately $item = Get-Item -Path $path If ( $item -is [System.IO.FileInfo] ) { ProcessFile $item ; Continue } # Get all children of $path ForEach ( $item in (Get-ChildItem -Path $path -Recurse -Force -ErrorAction SilentlyContinue) ) { # Process each file If ( $item -is [System.IO.FileInfo] ) { ProcessFile $item } } } Write-Output ('Total Files: {0}' -f ($IncludedFiles.Count)) If ( $IncludedFiles.Count -gt 0 ) { $IncludedFilesSize = 0 ForEach ($len in $IncludedFiles.Values) { $IncludedFilesSize += $len} Write-Output $('Total size: {0}GB' -f [math]::Round(($IncludedFilesSize/1GB),2) ) } Write-Output ('Total Excluded Files: {0}' -f ($FilteredFiles.Count)) If ( $FilteredFiles.Count -gt 0 ) { $FilteredFilesSize = 0 ForEach ($len in $FilteredFiles.Values) { $FilteredFilesSize += $len} Write-Output $('Total size: {0}GB' -f [math]::Round(($FilteredFilesSize/1GB),2) ) Write-Output "All files excluded from plan:" ForEach ($file in $FilteredFiles.GetEnumerator()) { Write-Output $file.Name } } Write-Output '' }