OneDriveForBusinessAdmin.ps1
<#PSScriptInfo
.VERSION 6.1 .GUID f9c18987-9ca5-4046-a357-8800a5671227 .AUTHOR Aaron Guilmette .COMPANYNAME Microsoft .COPYRIGHT 2020 .TAGS .LICENSEURI .PROJECTURI https://www.undocumented-features.com/2017/08/25/onedrive-for-business-admin-tool/ .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES .DESCRIPTION OneDrive for Business Management Tool. .PRIVATEDATA #> <# .SYNOPSIS OneDrive for Business Management Tool. .PARAMETER BlockAccess Block or unblock access to OneDrive for Business sites. .PARAMETER Confirm Use this switch parameter to confirm file or folder deletions. .PARAMETER Credential Used to store a credential object for connecting to SharePoint Online. .PARAMETER DeleteFilePattern Delete files matching pattern in a given OD4B site. For example, deleteing all MP4 files. Must use Confirm switch to delete files; otherwise, log only. Use a regular expression to ensure proper deletion. .PARAMETER FilesModifiedOnThisDate Use this parameter to specify the modified-on date for file version restores. For example, if you have to restore the version prior to the last modification 5 dates ago, you could specifiy ((Get-Date).AddDays(-5)). .PARAMETER FolderSize Use this parameter to return the folder size for the specified users. Folder size does NOT include version history storage (only final version). Output in the "Note" column is in megabytes (MB). .PARAMETER FolderToAdd String parameter with the name of a folder to add to all matching OneDrive for Business sites. You must have permissions to create folders in the target users' OneDrive for Business sites. You can use the GrantPermissions parameter to grant necessary permissions. .PARAMETER FolderToDelete String parameter witih the name of a folder to delete from all matching OneDrive for Business sites. You must have permissions to create folders in the target users' OneDrive for Business sites. You can use the GrantPermissions parameter to grant necessary permissions. You'll need to use -Confirm if you actually want to delete the folder. .PARAMETER GrantPermissions Grant permissions to a user account. User is made a secondary site collection administrator. Useful for delegating permissions for eDiscovery. .PARAMETER GrantPermissionsTo Grant permissions to the user specified in this parameter. If no user is specified, use the value stored in the Credential. .PARAMETER HoldStatus Check for In-Place Holds applied to OD4B sites (beta). .PARAMETER Identity Specify an individual user (by UPN or email address) for OneDrive admin operations. If no identity is specified, run against all enumerated OneDrive for Business sites. .PARAMETER InputFile List of UPNs or Email addresses for OneDrive for Business sites. If no file is specified, run against all enumerated OneDrive for Business sites. .PARAMETER ListOneDriveSites Generate a list of all OD4B sites. .PARAMETER ListOneDriveSitesOutput Output file for listing of OD4B sites. .PARAMETER Logfile Logfile for operations. .PARAMETER RestoreVerions Restore OneDrive for Business files in a site from saved versions. .PARAMETER RevokePermissions Revoke permissions for OneDrive for Business sites. .PARAMETER RevokePermissionsFor Revoke permissions of the named user. If no user is specified, uses the value stored in the credential. .PARAMETER Tenant SharePoint online tenant name (e.g., contoso or contoso.onmicrosoft.com) .PARAMETER VersionsToGoBack Specify number of versions of files to restore. By default, go back one version. .EXAMPLE .\OneDriveForBusinessAdmin.ps1 -Credential (Get-Credential) -GrantPermissions -GrantPermissionsTo aylakol@contoso.com Grant permissions to aylakol@contoso.com to all OneDrive for Business sites. .EXAMPLE .\OneDriveForBusinessAdmin.ps1 -Credential (Get-Credential) -GrantPermissions -FolderToAdd "Sales Orders" -FolderToDelete "Shared with Everyone" Grant permissions to the user specified in -Credential, add the folder "Sales Orders" to the "Documents" document library, and remove the "Shared with Everyone" folder from the "Documents" document library. .EXAMPLE .\OneDriveForBusinessAdmin.ps1 -Credential (Get-Credential) -GrantPermissions -DeleteFilePattern "\.mp4$" -Confirm Grant permissions to the user specified in *Get-Credential) and delete files with extension matching .mp4. .EXAMPLE .\OneDriveForBusinessAdmin.ps1 -Credential (Get-Credential) -Tenant ems340903 -ListOneDriveSites Generate a list of all OneDrive for Business sites and output to default location. .LINK https://aka.ms/OneDriveAdmin .LINK https://undocumented-features.com/2017/08/25/onedrive-for-business-admin-tool/ .LINK https://undocumented-features.com/2017/10/16/recovering-from-crypto-or-ransomware-attacks-with-the-onedrive-for-business-admin-tool/ .NOTES 2020-04-20 Updated for PowerShell Gallery. 2019-08-01 Updates/clarity in messages based on user feedback, text alignment updates. 2019-05-15 Added HoldStatus check (beta). 2018-10-04 Added ListOneDriveSites parameter. Fixed Identity parameter bug when submitting multiple users via command-line interface. 2018-09-15 Added FolderSize parameter. 2018-01-10 Added DeleteFilePattern parameter. Updated LogFile parameter to always generate. 2017-10-16 Added Identity and RestoreVersions parameters 2017-09-05 Added TrimEnd("/") to BlockAccess function 2017-08-24 Initial release. #> Param ( [ValidateSet('Block','Unblock')] [string]$BlockAccess, [Parameter(Mandatory = $false, HelpMessage = 'Confirm removal of the folders')] [switch]$Confirm, [Parameter(Mandatory = $true)] [System.Management.Automation.PSCredential]$Credential, [Parameter(Mandatory = $false)] [regex]$DeleteFilePattern, [Parameter(Mandatory = $false)] [datetime]$FilesModifiedOnThisDate, [Parameter(Mandatory = $false)] [switch]$FolderSize, [Parameter(Mandatory = $false, HelpMessage = 'Folder to add')] [string]$FolderToAdd, [Parameter(Mandatory = $false, HelpMessage = 'Folder to delete')] [string]$FolderToDelete, [Parameter(mandatory = $false)] [Switch]$GrantPermissions, [Parameter(Mandatory = $false)] [string]$GrantPermissionsTo, [switch]$HoldStatus, [array]$Identity, [String]$InputFile, [switch]$ListOneDriveSites, [string]$ListOneDriveSitesOutput = (Get-Date -Format yyyy-MM-dd) + "_OneDriveForBusinessSiteList.csv", [Parameter(mandatory = $false)] [String]$LogFile = (Get-Date -Format yyyy-MM-dd) + "_OneDriveForBusinessAdminLog.csv", [Parameter(Mandatory = $false)] [ValidateSet('ByDate', 'ByNumberOfVersionsToGoBack')] [String]$RestoreVersions, [Parameter(mandatory = $false)] [Switch]$RevokePermissions, [Parameter(Mandatory = $false)] [string]$RevokePermissionsFor, [Parameter(mandatory = $true)] [String]$Tenant, [Parameter(Mandatory = $false)] [int]$VersionsToGoBack ) # End Parameters $ErrorActionPreference = 'SilentlyContinue' $WarningPreference = 'SilentlyContinue' If ($HoldStatus) { If (!(Get-Command Get-CaseHoldPolicy -ea silently continue)) { try { $ComplianceSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid -Credential $Credential -Authentication Basic -AllowRedirection Import-PSSession $ComplianceSession -ea silentlycontinue -wa silentlycontinue } catch { } If (!(Get-Command Get-EDiscoveryCaseAdmin -ea silentlycontinue)) { Write-Warning -Message "Current user is not a member of eDiscovery Case Admins. If holds are applied to OD4B sites as part of an eDiscovery case, the case identity may not be fully resolved, though the GUID will be visible." } } } function LogWrite($Function,$User,$OD4BSite,$FolderName,$Note,$VersionLabel) { $LogData = """" + $Function + """" + "," + """" + $User + """"+ "," + """" + $OD4BSite + """" + "," + """" + $FolderName + """" + "," + """" + $Note + """" + "," + """" + $VersionLabel + """" Add-Content -Path $LogFile -Value $LogData } # End Function LogWrite function ListOneDriveSites($OD4BSite, $User) { $OD4BSite = $OD4BSite.TrimEnd("/") $Data = """" + $($User) + """" + "," + """" + $OD4BSite + """" LogWrite -Function "ListOneDriveSites" -User $User -OD4BSite $OD4BSite Add-Content -Path $ListOneDriveSitesOutput -Value $Data } # End Function ListOneDriveSites function BlockOneDriveAccess($OD4BSite, $AccessState) { $OD4BSite = $OD4BSite.TrimEnd("/") Switch ($AccessState) { Block { Write-Host "AccessState Should be set to NoAccess." Get-SPOSite -Identity $OD4BSite | Set-SPOSite -LockState NoAccess If ($LogFile) { LogWrite -Function "$($MyInvocation.MyCommand)-$AccessState.ToString()" -OD4BSite $OD4BSite } $State = ((Get-SPOSite -Identity $OD4BSite).LockState) Write-Host "Access state is: " $State Write-Host "-----------------------------------------------------------------------" } Unblock { Write-Host "AccessState Should be set to Unlock." Get-SPOSite -Identity $OD4BSite | Set-SPOSite -LockState Unlock If ($LogFile) { LogWrite -Function "$($MyInvocation.MyCommand)-$AccessState.ToString()" -OD4BSite $OD4BSite } $State = ((Get-SPOSite -Identity $OD4BSite).LockState) Write-Host "Access state is: " $State Write-Host "-----------------------------------------------------------------------" } } } # End Function BlockOneDriveAccess Function GrantPermissions($User, $OD4BSite) { Write-Host -ForegroundColor Green " Granting permissions on $OD4BSite to $User" Set-SPOUser -Site $OD4BSite -LoginName $User -IsSiteCollectionAdmin $true | Out-Null If ($LogFile) { LogWrite -Function $MyInvocation.MyCommand -User "$($User)" -OD4BSite "$($OD4BSite)" } } # End Function GrantPermissions Function RevokePermissions($User, $OD4BSite) { Write-Host -ForegroundColor Green " Revoking permissions on $($OD4BSite) for $($User)" Get-SPOUser -Site $OD4BSite.TrimEnd("/") If ($LogFile) { LogWrite -Function $MyInvocation.MyCommand -User "$($User)" -OD4BSite "$($OD4BSite)" } } # End Function RevokePermissions Function AddFolder($FolderName,$OD4BSite) { Write-Host "Adding Folder Documents/$($FolderName)" $Folder = $personalWeb.Folders.Add("Documents" + "/" + $FolderName) $ClientContextSource.Load($personalWeb) $ClientContextSource.Load($personalWeb.Folders) $ClientContextSource.ExecuteQuery() If ($LogFile) { LogWrite -Function $MyInvocation.MyCommand -FolderName "$($FolderName)" -OD4BSite "$($OD4BSite)" } } # End Function AddFolder Function RemoveFolder($FolderName,$OD4BSite,$User) { # Delete Specified Folder foreach ($toBeDeleted in $allFolders) { #Write-Host "Examining Folder" $toBeDeleted.Name if ($toBeDeleted.Name -eq $FolderName) { #Write-Host -Fore Green " $($FolderName) present in $OD4BPath" If ($Confirm) { Write-Host -ForegroundColor Cyan " ** Confirm enabled. Deleting Folder " $toBeDeleted.Name $toBeDeleted.DeleteObject() $personalWeb.Update() $ClientContextSource.ExecuteQuery() If ($LogFile) { LogWrite -Function $MyInvocation.MyCommand -FolderName "$($FolderName)" -OD4BSite "$($OD4BSite)" } } Else { Write-Host -ForegroundColor Yellow "No action taken on $($toBeDeleted). Use -Confirm parameter to delete." } } } } # End Function RemoveFolder function DeleteFilePattern($Pattern, $OD4BSite) { If ($Confirm) { $global:FilesToDelete = @() foreach ($obj in $allItems) { If ($obj["FileRef"] -match $Pattern) { #write-host "File $($obj["FileRef"]) matches. Deleting." #$obj.DeleteObject()) $FilesToDelete += $obj #$ClientContextSource.ExecuteQuery() If ($LogFile) { LogWrite -Function "DeleteFilePattern" -OD4BSite $OD4BSite -Note "File $($obj["FileRef"]) deleted." } } } $FilesToDelete.DeleteObject() $ClientContextSource.ExecuteQuery() } Else { foreach ($obj in $allItems) { If ($obj["FileRef"] -match $Pattern) { write-host "File $($obj["FileRef"]) matches. Specify Confirm switch to delete."; If ($LogFile) { LogWrite -Function "DeleteFilePattern-LogOnly" -OD4BSite $OD4BSite -Note "File $($obj["FileRef"]) would have been deleted." } } } } } function HoldStatus($OD4BSite, $User) { # Explicit holds $LibraryStatus = $personalWeb.AllProperties $ClientContextSource.Load($LibraryStatus) $ClientContextSource.ExecuteQuery() [array]$holdstemp = $LibraryStatus.FieldValues.allwebholds -split ";" $holds = @() foreach ($obj in $holdstemp) { $o = $obj.Split(",")[0] $holds += $o } [pscustomobject]$HoldPolicies = @() foreach ($policy in $holds) { If (!($policy -eq "")) { $HoldPolicies = Get-RetentionCompliancePolicy $policy | select ` @{ N = "Hold"; E = { $_.Name } }, @{ N = "Policy Guid"; E = { $policy } } If (!($HoldPolicies.Hold -eq "")) { $HoldString = "$($HoldPolicies.Hold) - $($HoldPolicies.'Policy Guid')" } else { $HoldString = "<unable to resolve> - $($HoldPolicies.'Policy Guid')"} Write-Host "$($OD4BSite) has the following holds applied to it: $HoldString" LogWrite -Function "HoldStatus" -User $User -OD4BSite $OD4BSite -Note $HoldString } } } function FolderSize($OD4BSite,$User) { If ($docList.BaseType -eq "DocumentLibrary") { $BatchSize = 1000 $TotalLibrarySize = 0 $FileCount = 0 $docSize = 0 $camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery $camlQuery.ViewXml = "<View Scope='RecursiveAll'><RowLimit Paged='True'>$BatchSize</RowLimit></View>"; $allLibraryItems = $doclist.GetItems($camlQuery) $ClientContextSource.Load($allLibraryItems) $ClientContextSource.ExecuteQuery() foreach ($item in $allLibraryItems) { $FileCount++ if ($item.FileSystemObjectType -eq "File") { $file = $item.File $fItem = $file.ListItemAllFields $ClientContextSource.Load($file) $ClientContextSource.Load($fItem) $ClientContextSource.ExecuteQuery() $docSize = $fItem["File_x0020_Size"] [int]$TotalLibrarySize += $docSize # To output each file individually to screen for troubleshooting, uncomment #Write-Host "$($docList.Title), $($file.ServerRelativeUrl), $($fItem["FileLeafRef"].Split('.')[0]), $($docSize) KB" } } $TotalLibrarySize = $TotalLibrarySize/1048576 Write-Host "$($User) folder total size is $($TotalLibrarySize) MB in $($FileCount) files." LogWrite -Function FolderSize -User $($User) -OD4BSite $OD4BSite -Note $TotalLibrarySize } ## } # End Function FolderSize ### Script component prerequisites Write-Host -Fore Yellow "Locating SharePoint Server Client Components installation..." If (Test-Path 'c:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll') { Write-Host -ForegroundColor Green "Found SharePoint Server Client Components installation." Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll" Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll" Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Taxonomy.dll" Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.UserProfiles.dll" } ElseIf ($filename = (Get-ChildItem 'C:\Program Files' -Recurse -ea silentlycontinue | where { $_.name -eq 'Microsoft.SharePoint.Client.DocumentManagement.dll' })[0]) { $Directory = ($filename.DirectoryName)[0] Write-Host -ForegroundColor Green "Found SharePoint Server Client Components at $Directory." Add-Type -Path "$Directory\Microsoft.SharePoint.Client.dll" Add-Type -Path "$Directory\Microsoft.SharePoint.Client.Runtime.dll" Add-Type -Path "$Directory\Microsoft.SharePoint.Client.Taxonomy.dll" Add-Type -Path "$Directory\Microsoft.SharePoint.Client.UserProfiles.dll" } ElseIf (!(Test-Path 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll')) { Write-Host -ForegroundColor Yellow "This script requires the SharePoint Server Client Components. Attempting to download and install." wget 'https://download.microsoft.com/download/E/1/9/E1987F6C-4D0A-4918-AEFE-12105B59FF6A/sharepointclientcomponents_15-4711-1001_x64_en-us.msi' -OutFile ./SharePointClientComponents_15.msi wget 'https://download.microsoft.com/download/F/A/3/FA3B7088-624A-49A6-826E-5EF2CE9095DA/sharepointclientcomponents_16-4351-1000_x64_en-us.msi' -OutFile ./SharePointClientComponents_16.msi msiexec /i SharePointClientComponents_15.msi /qb msiexec /i SharePointClientComponents_16.msi /qb Sleep 60 If (Test-Path 'c:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll') { Write-Host -ForegroundColor Green "Found SharePoint Server Client Components." Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll" Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll" Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Taxonomy.dll" Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.UserProfiles.dll" } Else { Write-Host -NoNewLine -ForegroundColor Red "Please download the SharePoint Server Client Components from " Write-Host -NoNewLine -ForegroundColor Yellow "https://download.microsoft.com/download/F/A/3/FA3B7088-624A-49A6-826E-5EF2CE9095DA/sharepointclientcomponents_16-4351-1000_x64_en-us.msi " Write-Host -ForegroundColor Red "and try again." Break } } If (!(Get-Module -ListAvailable "*online.sharepoint*")) { Write-Host -ForegroundColor Yellow "This script requires the SharePoint Online Management Shell. Attempting to download and install." wget 'https://download.microsoft.com/download/0/2/E/02E7E5BA-2190-44A8-B407-BC73CA0D6B87/SharePointOnlineManagementShell_6802-1200_x64_en-us.msi' -OutFile ./SharePointOnlineManagementShell.msi msiexec /i SharePointOnlineManagementShell.msi /qb Write-Host -ForegroundColor Yellow "Please close and reopen the Windows Azure PowerShell module and re-run this script." } ### End script component prerequisites If ($InputFile -and $Identity) { Write-Host -ForegroundColor Red "Only InputFile or Identity may be specified on the command line (or neither to include all users)." Break } If ($LogFile) { If (!(Test-Path $LogFile)) { Write-Host -ForegroundColor Yellow "Log file not found. Creating $($LogFile)." # Params that can be passed to LogWrite: $Function, $User, $OD4BSite, $FolderName, $Note, $VersionLabel $LogFileHeader = """" + "Function" + """" + "," + """" + "User" + """" + "," + """" + "OD4BSite" + """" + "," + """" + "FolderName" + """" + "," + """" + "Note" + """" + "," + """" + "VersionLabel" + """" $LogFileHeader | Out-File $LogFile } Else { Write-Host -ForegroundColor Yellow "Existing log file found. Appending." } } If ($ListOneDriveSites) { If (!(Test-Path $ListOneDriveSitesOutput)) { Write-Host -ForegroundColor Yellow "One Drive Site List output file not found. Creating $($ListOneDriveSitesOutput)." $ListHeader = """" + "UserPrincipalName" + """" + "," + """" + "OD4BSite" + """" $ListHeader | Out-File $ListOneDriveSitesOutput } } ## Variables # Define URLs If ($tenant -like "*.onmicrosoft.com") { $tenant = $tenant.split(".")[0] } $MySiteURL = "https://$tenant-my.sharepoint.com" $AdminURL = "https://$tenant-admin.sharepoint.com" # Define Contexts $Context = New-Object Microsoft.SharePoint.Client.ClientContext($MySiteURL) # Define Credentials $Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Credential.Username, $Credential.Password) $Context.Credentials = $Creds # Connect to SPO Service for granting permissions if necessary Connect-SPOService -url $AdminURL -credential $Credential # Get OD4B WebSite Users $Users = $Context.Web.SiteUsers $Context.Load($Users) $Context.ExecuteQuery() $peopleManager = New-Object Microsoft.SharePoint.Client.UserProfiles.PeopleManager($Context) # Set user list to $Context.WebSite.Users if no input file is found If ($InputFile) { $UserList = Import-Csv -Header UserPrincipalName $UserList = $UserList.UserPrincipalName -join "|" [array]$users = $Users.LoginName | ? { $_ -match $UserList } } If ($Identity) { If ($Identity.Count -gt 1) { $UserList = $Identity -join "|" } else { $UserList = $Identity } #Write-Host "UserList is $($UserList)" [array]$Users = $Users.LoginName | ? { $_ -match $UserList } } # Define GrantPermissionsTo and RevokePermissionsFrom Users If (!$GrantPermissionsTo) { $GrantPermissionsTo = $Credential.UserName } If (!$RevokePermissionsFor) { $RevokePermissionsFor = $Credential.UserName } foreach ($User in $Users) { # select $User to load into $UserProfile If ($Identity) { $userProfile = $peopleManager.GetPropertiesFor($User) } Else { $userProfile = $peopleManager.GetPropertiesFor($user.LoginName) } # Update $userProfile var $Context.Load($userProfile) $Context.ExecuteQuery() # Check to see if the User has an email address and a OD4B site provisioned if ($userProfile.Email -ne $null -and $userProfile.UserProfileProperties.PersonalSpace -ne "") { $i++ $OD4BPath = $MySiteURL + $userProfile.UserProfileProperties.PersonalSpace Write-Host -ForegroundColor Green "Processing $($OD4BPath) for $($userProfile.UserProfileProperties.PreferredName)..." # $userProfile.UserProfileProperties.PersonalSpace # If the $GrantPermissions switch is present, execute the GrantPermissions function If ($GrantPermissions) { GrantPermissions -User $GrantPermissionsTo -OD4BSite $OD4BPath } If ($RevokePermissions) { RevokePermissions -User $RevokePermissionsFor -OD4BSite $OD4BPath } If ($BlockAccess) { BlockOneDriveAccess -OD4BSite $OD4BPath -AccessState $BlockAccess } # If OD4BPath is present, enumerate folders for various operations if (($HoldStatus -or $FolderToAdd -or $FolderToDelete -or $DeleteFilePattern -or $FolderSize) -and $OD4BPath) { $ClientContextSource = New-Object Microsoft.SharePoint.Client.ClientContext($OD4BPath); $ClientContextSource.Credentials = $Creds $ClientContextSource.ExecuteQuery() $personalWeb = $ClientContextSource.Web $ClientContextSource.Load($personalWeb) $ClientContextSource.ExecuteQuery() $docList = $personalWeb.Lists.GetByTitle("Documents") $ClientContextSource.Load($docList) $ClientContextSource.Load($personalWeb.Folders) $ClientContextSource.ExecuteQuery() $allFolders = $docList.RootFolder.Folders $ClientContextSource.Load($allFolders) $ClientContextSource.ExecuteQuery() # Get Hold status If ($HoldStatus) { HoldStatus -OD4BSite $OD4BPath -User $($userProfile.Email) } # Get Folder Size If ($FolderSize) { FolderSize -OD4BSite $OD4BPath -User $($userProfile.Email) } # Remove Folder If ($FolderToDelete) { RemoveFolder -FolderName $FolderToDelete } # Add folder If ($FolderToAdd) { AddFolder -FolderName $FolderToAdd } # Delete files matching pattern If ($DeleteFilePattern) { $Library = $ClientContextSource.Web.Lists.GetByTitle("Documents") $ClientContextSource.Load($Library) $ClientContextSource.ExecuteQuery() $CamlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery $CamlQuery.ViewXml = "<View Scope='RecursiveAll' />" $AllItems = $Library.GetItems($camlQuery) $ClientContextSource.Load($AllItems) $ClientContextSource.ExecuteQuery() If ($Confirm) { DeleteFilePattern -Pattern $DeleteFilePattern -Confirm } Else { DeleteFilePattern -Pattern $DeleteFilePattern } } # End DeleteFilePattern } # End If FolderToAdd or FolderToDelete or DeleteFilePattern If ($RestoreVersions) { # Load items and versions $ClientContextSource = New-Object Microsoft.SharePoint.Client.ClientContext($OD4BPath); $ClientContextSource.Credentials = $Creds $ClientContextSource.ExecuteQuery() $personalWeb = $ClientContextSource.Web $ClientContextSource.Load($personalWeb) $ClientContextSource.ExecuteQuery() $docList = $personalWeb.Lists.GetByTitle("Documents") $ClientContextSource.Load($docList) $ClientContextSource.Load($personalWeb.Folders) $ClientContextSource.ExecuteQuery() $allFolders = $docList.RootFolder.Folders $ClientContextSource.Load($allFolders) $ClientContextSource.ExecuteQuery() $VersionQuery = New-Object Microsoft.SharePoint.Client.CamlQuery $VersionQuery.ViewXml = "<View Scope = 'RecursiveAll' />" $ItemsToRestore = $docList.GetItems($VersionQuery) $ClientContextSource.Load($ItemsToRestore) $ClientContextSource.ExecuteQuery() foreach ($item in $ItemsToRestore) { $File = $ClientContextSource.Web.GetFileByServerRelativeUrl($item["FileRef"]) $ClientContextSource.Load($File) $ClientContextSource.Load($File.Versions) #$ClientContextSource.Load($File.ServerRelativeUrl) ### Try { $ClientContextSource.ExecuteQuery() Write-Host File versions $File.Versions.Count $File.ServerRelativeUrl } Catch { Continue; } If ($File.Versions.Count -eq 0) { Write-Host No vesions to restore. $LogData = New-Object PSCustomObject $LogData | Add-Member NoteProperty ServerRelativeUrl($File.ServerRelativeUrl) $LogData | Add-Member NoteProperty FileLeafRef($item["FileLeafRef"]) $LogData | Add-Member NoteProperty Versions("No Versions Available") If ($LogFile) { LogWrite -Function "RestoreVersionsFailed" -User $User -Note $LogData.ServerRelativeUrl } } ElseIf ($File.TypedObject.ToString() -eq "Microsoft.SharePoint.Client.File") { #foreach ($Version in $File.Versions) #{ #$File.Versions | FL Switch($RestoreVersions) { ByDate { If (!($FilesModifiedOnThisDate)) { Write-Host -ForegroundColor Red "You must specify a value for FilesModifiedOnThisDate." Break } [array]$FileRestoreCandidates = $File.Versions | ? { $_.Created -le $FilesModifiedOnThisDate } | Sort -Property Created If ($FileRestoreCandidates.Count -lt 2) { Write-Host -ForegroundColor Red "No versions available matching date criteria for $($File.ServerRelativeUrl)." Continue } Else { # Select the most current version in the $VersionLabel = $FileRestoreCandidates[-2].VersionLabel Write-Host "Version to be restored: " $VersionLabel } $File.Versions.RestoreByLabel($VersionLabel) $ClientContextSource.ExecuteQuery() If ($LogFile) { LogWrite -Function "FileRestored" -User $User -Note $LogData.ServerRelativeUrl -VersionLabel $VersionLabel } } ByNumberOfVersionsToGoBack { if ($File.Versions[($File.Versions.Count - 1)].IsCurrentVersion) { Write-Host $File.Name $Version.Created $Version.Size $Version.VersionLabel $Version.IsCurrentVersion $File.Versions.Count $VersionLabel = $File.Versions[($File.Versions.Count - 2)].VersionLabel Write-Host "Version to be restored: " $VersionLabel } elseif ($VersionsToGoBack -and $VersionsToGoBack -le $File.Versions.Count) { Write-Host "Versions to go back specified as $($VersionsToGoBack)" $VersionLabel = $File.Versions[($File.Versions.Count - $VersionsToGoBack)].VersionLabel Write-Host "Version to be restored: " $VersionLabel } else { $VersionLabel = $File.Versions[($File.Versions.Count - 2)].VersionLabel Write-Host "Version to be restored: " $VersionLabel } $File.Versions.RestoreByLabel($VersionLabel) $ClientContextSource.ExecuteQuery() If ($LogFile) { LogWrite -Function "FileRestored" -User $User -Note $LogData.ServerRelativeUrl -VersionLabel $VersionLabel } } # End Select "ByNumberOfversionsToGoBack" } # End Select #} #End Foreach $Version } # End ElseIf } # End Foreach $Item in $ItemsToRestore } # End RestoreVersions If ($ListOneDriveSites) { ListOneDriveSites -User $($userProfile.Email) -OD4BSite $OD4BPath } } } |