Script to add users to a hold
Original from this Microsoft page
#script begin " " write-host "***********************************************" write-host " Office 365 Security & Compliance Center " -foregroundColor yellow -backgroundcolor darkgreen write-host " eDiscovery cases - Add users to a hold " -foregroundColor yellow -backgroundcolor darkgreen write-host "***********************************************" " " # Get user credentials & Connect to Office 365 SCC, SPO $credentials = Get-Credential -Message "Specify your credentials to connect to the Office 365 Security & Compliance Center and SharePoint Online" $s = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://ps.compliance.protection.outlook.com/powershell-liveid" -Credential $credentials -Authentication Basic -AllowRedirection -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck) $a = Import-PSSession $s -AllowClobber if (!$s) { Write-Error "Couldn't create PowerShell session." return; } # Load the SharePoint assemblies from the SharePoint Online Management Shell # To install, go to http://go.microsoft.com/fwlink/p/?LinkId=255251 if (!$SharePointClient -or !$SPRuntime -or !$SPUserProfile) { $SharePointClient = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client") $SPRuntime = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime") $SPUserProfile = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.UserProfiles") if (!$SharePointClient) { Write-Error "The SharePoint Online Management Shell isn't installed. Please install it from: http://go.microsoft.com/fwlink/p/?LinkId=255251 and then re-run this script." return; } } if (!$spCreds) { $spCreds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($credentials.UserName, $credentials.Password) } # Get the user's MySite domain name. We use this to create the admin URL and root URL for OneDrive for Business "" $mySiteDomain = Read-Host "Enter the name of your organization's MySite domain. For example, 'contoso' for 'https://contoso-my.sharepoint.com'" "" # Get other required information do{ $casename = Read-Host "Enter the name of the case" $caseexists = (get-compliancecase -identity "$casename" -erroraction SilentlyContinue).isvalid if($caseexists -ne 'True') {"" write-host "A case named '$casename' doesn't exist. Please specify the name of an existing case, or create a new case and then re-run the script." -foregroundColor Yellow ""} }While($caseexists -ne 'True') "" do{ $holdName = Read-Host "Enter the name of the new hold" $holdexists=(get-caseholdpolicy -identity "$holdname" -case "$casename" -erroraction SilentlyContinue).isvalid if($holdexists -eq 'True') {"" write-host "A hold named '$holdname' already exists. Please specify a new hold name." -foregroundColor Yellow ""} }While($holdexists -eq 'True') "" $holdQuery = Read-Host "Enter a search query to create a query-based hold, or press Enter to hold all content" "" $holdstatus = read-host "Do you want the hold enabled after it's created? (Yes/No)" do{ "" $inputfile = read-host "Enter the name of the text file that contains the email addresses of the users to add to the hold" "" $fileexists = test-path -path $inputfile if($fileexists -ne 'True'){write-host "$inputfile doesn't exist. Please enter a valid file name." -foregroundcolor Yellow} }while($fileexists -ne 'True') #Import the list of addresses from the txt file. Trim any excess spaces and make sure all addresses #in the list are unique. [array]$emailAddresses = Get-Content $inputfile -ErrorAction SilentlyContinue | where {$_.trim() -ne ""} | foreach{ $_.Trim() } [int]$dupl = $emailAddresses.count [array]$emailAddresses = $emailAddresses | select-object -unique $dupl -= $emailAddresses.count #Validate email addresses so the hold creation does not run in to an error. if($emailaddresses.count -gt 0){ write-host ($emailAddresses).count "addresses were found in the text file. There were $dupl duplicate entries in the file." -foregroundColor Yellow "" Write-host "Validating the email addresses. Please wait..." -foregroundColor Yellow "" $finallist =@() foreach($emailAddress in $emailAddresses) { if((get-recipient $emailaddress -erroraction SilentlyContinue).isvalid -eq 'True') {$finallist += $emailaddress} else {"Unable to find the user $emailaddress" [array]$excludedlist += $emailaddress} } "" #find user's OneDrive Site URL using email address Write-Host "Getting the URL for each user's OneDrive for Business site." -foregroundColor Yellow "" $AdminUrl = "https://$mySiteDomain-admin.sharepoint.com" $mySiteUrlRoot = "https://$mySiteDomain-my.sharepoint.com" # Add the path of the User Profile Service to the SPO admin URL, then create a new webservice proxy to access it $proxyaddr = "$AdminUrl/_vti_bin/UserProfileService.asmx?wsdl" $UserProfileService= New-WebServiceProxy -Uri $proxyaddr -UseDefaultCredential False $UserProfileService.Credentials = $credentials # Take care of auth cookies $strAuthCookie = $spCreds.GetAuthenticationCookie($AdminUrl) $uri = New-Object System.Uri($AdminUrl) $container = New-Object System.Net.CookieContainer $container.SetCookies($uri, $strAuthCookie) $UserProfileService.CookieContainer = $container $urls = @() foreach($emailAddress in $emailAddresses) { try{ $prop = $UserProfileService.GetUserProfileByName("i:0#.f|membership|$emailAddress") | Where-Object { $_.Name -eq "PersonalSpace" } $url = $prop.values[0].value if($url -ne $null){ $furl = $mySiteUrlRoot + $url $urls += $furl Write-Host "- $emailAddress => $furl" [array]$ODadded += $furl} else{ Write-Warning "Couldn't locate OneDrive for $emailAddress" [array]$ODExluded += $emailAddress }} catch { Write-Warning "Could not locate OneDrive for $emailAddress" [array]$ODExluded += $emailAddress Continue } } if(($finallist.count -gt 0) -or ($urls.count -gt 0)){ "" Write-Host "Creating the hold named $holdname. Please wait..." -foregroundColor Yellow if(($holdstatus -eq "Y") -or ($holdstatus -eq "y") -or ($holdstatus -eq "yes") -or ($holdstatus -eq "YES")){ New-CaseHoldPolicy -Name "$holdName" -Case "$casename" -ExchangeLocation $finallist -SharePointLocation $urls -Enabled $True | out-null New-CaseHoldRule -Name "$holdName" -Policy "$holdname" -ContentMatchQuery $holdQuery | out-null } else{ New-CaseHoldPolicy -Name "$holdName" -Case "$casename" -ExchangeLocation $finallist -SharePointLocation $urls -Enabled $false | out-null New-CaseHoldRule -Name "$holdName" -Policy "$holdname" -ContentMatchQuery $holdQuery -disabled $true | out-null } "" } else {"No valid locations were identified. Therefore, the hold wasn't created."} #write log files (if needed) $newhold=Get-CaseHoldPolicy -Identity "$holdname" -Case "$casename" -erroraction SilentlyContinue $newholdrule=Get-CaseHoldRule -Identity "$holdName" -erroraction SilentlyContinue if(($ODAdded.count -gt 0) -or ($ODExluded.count -gt 0) -or ($finallist.count -gt 0) -or ($excludedlist.count -gt 0) -or ($newhold.isvalid -eq 'True') -or ($newholdrule.isvalid -eq 'True')) { Write-Host "Generating output files..." -foregroundColor Yellow if($ODAdded.count -gt 0){ "OneDrive Locations" | add-content .\LocationsOnHold.txt "==================" | add-content .\LocationsOnHold.txt $newhold.SharePointLocation.name | add-content .\LocationsOnHold.txt} if($ODExluded.count -gt 0){ "Users without OneDrive locations" | add-content .\LocationsNotOnHold.txt "================================" | add-content .\LocationsNotOnHold.txt $ODExluded | add-content .\LocationsNotOnHold.txt} if($finallist.count -gt 0){ " " | add-content .\LocationsOnHold.txt "Exchange Locations" | add-content .\LocationsOnHold.txt "==================" | add-content .\LocationsOnHold.txt $newhold.ExchangeLocation.name | add-content .\LocationsOnHold.txt} if($excludedlist.count -gt 0){ " "| add-content .\LocationsNotOnHold.txt "Mailboxes not added to the hold" | add-content .\LocationsNotOnHold.txt "===============================" | add-content .\LocationsNotOnHold.txt $excludedlist | add-content .\LocationsNotOnHold.txt} $FormatEnumerationLimit=-1 if($newhold.isvalid -eq 'True'){$newhold|fl >.\GetCaseHoldPolicy.txt} if($newholdrule.isvalid -eq 'True'){$newholdrule|Fl >.\GetCaseHoldRule.txt} } } else {"The hold wasn't created because no valid entries were found in the text file."} "" Write-host "Script complete!" -foregroundColor Yellow "" #script end