Create a report on holds in eDiscovery cases in Office 365

Note: The script in this article has been updated to fix an issue where content locations placed on hold weren't being included in the report. Thanks to the customer who brought this to our attention!

The script in this article lets eDiscovery administrators and eDiscovery managers generate a report that contains information about all holds that are associated with eDiscovery cases in the Office 365 Security & Compliance Center. The report contains information such as the name of the case a hold is associated with, the content locations that are placed on hold, and whether the hold is query-based. See the More information section for a detailed description of the information included in the report.

Before you begin

  • To generate a report on all eDiscovery cases in your organization, you have to be an eDiscovery Administrator in your organization. If you are an eDiscovery Manager, the report will only include information about the cases that you can access. For more information about eDiscovery permissions, see Assign eDiscovery permissions in the Office‍ 365 Security & Compliance Center.

  • The script in this article has minimal error handling. The primary purpose is to quickly create report about the holds that are associated with the eDiscovery cases in your organization.

  • The sample scripts provided in this topic aren’t supported under any Microsoft standard support program or service. The sample scripts are provided AS IS without warranty of any kind. Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages.

Step 1: Connect to the Security & Compliance Center using Remote PowerShell

The first step is to connect Windows PowerShell to the Security & Compliance Center for your organization.

  1. Save the following text to a Windows PowerShell script file by using a filename suffix of .ps1; for example, ConnectSCC.ps1.

    # Get login credentials 
    $UserCredential = Get-Credential 
    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid -Credential $UserCredential -Authentication Basic -AllowRedirection 
    Import-PSSession $Session -AllowClobber -DisableNameChecking 
    $Host.UI.RawUI.WindowTitle = $UserCredential.UserName + " (Office 365 Security & Compliance Center)" 
    
  2. On your local computer, open Windows PowerShell and go to the folder where you saved the script.

  3. Run the script; for example:

    .\ConnectSCC.ps1
  4. When prompted for your credentials, enter your email address and password, and then click OK.

Return to top

Step 2: Run the script to report on holds associated with eDiscovery cases

After you've connected to the Security & Compliance Center with remote PowerShell, the next step is to create and run the script that collects information about the eDiscovery cases in your organization.

  1. Save the following text to a Windows PowerShell script file by using a filename suffix of .ps1; for example, CaseHoldsReport.ps1.

    #script begin
    " " 
    write-host "***********************************************"
    write-host "   Office 365 Security & Compliance Center   " -foregroundColor yellow -backgroundcolor darkgreen
    write-host "        eDiscovery cases - Holds report         " -foregroundColor yellow -backgroundcolor darkgreen 
    write-host "***********************************************"
    " " 
    
    #prompt users to specify a path to store the output files
    $time=get-date
    $Path = Read-Host 'Enter a file path to save the report to a .csv file'
    $outputpath=$Path+'\'+'CaseHoldsReport'+' '+$time.day+'-'+$time.month+'-'+$time.year+' '+$time.hour+'.'+$time.minute+'.csv'
    
    #add case details to the csv file
    
    function add-tocasereport{
    Param([string]$casename,
    [String]$casestatus,
    [datetime]$casecreatedtime,
    [string]$casemembers,
    [datetime]$caseClosedDateTime,
    [string]$caseclosedby,
    [string]$holdname,
    [String]$Holdenabled,
    [string]$holdcreatedby,
    [string]$holdlastmodifiedby,
    [string]$ExchangeLocation,
    [string]$sharePointlocation,
    [string]$ContentMatchQuery,
    [datetime]$holdcreatedtime,
    [datetime]$holdchangedtime
    )
    $addRow = New-Object PSObject 
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Case name" -Value $casename
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Case status" -Value $casestatus
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Case members" -Value $casemembers
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Case created time" -Value $casecreatedtime
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Case closed time" -Value $caseClosedDateTime
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Case closed by" -Value $caseclosedby
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Hold name" -Value $holdname
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Hold enabled" -Value $Holdenabled
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Hold created by" -Value $holdcreatedby
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Hold last changed by" -Value $holdlastmodifiedby
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Exchange locations" -Value  $ExchangeLocation
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "SharePoint locations" -Value $sharePointlocation
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Hold query" -Value $ContentMatchQuery
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Hold created time (UTC)" -Value $holdcreatedtime
    Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Hold changed time (UTC)" -Value $holdchangedtime
    
    $allholdreport = $addRow | Select-Object "Case name","Case status","Hold name","Hold enabled","Case members", "Case created time","Case closed time","Case closed by","Exchange locations","SharePoint locations","Hold query","Hold created by","Hold created time (UTC)","Hold last changed by","Hold changed time (UTC)"
    
    $allholdreport | export-csv -path $outputPath -notypeinfo -append -Encoding ascii 
    }
    
    #get information on the cases and pass values to the case report function
    
    " "
    write-host "Gathering a list of cases and holds..."
    " "
    $edc =Get-ComplianceCase -ErrorAction SilentlyContinue
    foreach($cc in $edc)
    {
    write-host "Working on case :" $cc.name
    if($cc.status -eq 'Closed')
    {
    $cmembers = ((Get-ComplianceCaseMember -Case $cc.name).windowsLiveID)-join ';'
    add-tocasereport -casename $cc.name -casestatus $cc.Status -caseclosedby $cc.closedby -caseClosedDateTime $cc.ClosedDateTime -casemembers $cmembers 
    }
    else{
    $cmembers = ((Get-ComplianceCaseMember -Case $cc.name).windowsLiveID)-join ';'
    $policies = Get-CaseHoldPolicy -Case $cc.Name | %{ Get-CaseHoldPolicy $_.Name -Case $_.CaseId -DistributionDetail}
    foreach ($policy in $policies)
    {
    $rule=Get-CaseHoldRule -Policy $policy.name
    add-tocasereport -casename $cc.name -casemembers $cmembers -casestatus $cc.Status -casecreatedtime $cc.CreatedDateTime -holdname $policy.name -holdenabled $policy.enabled -holdcreatedby $policy.CreatedBy -holdlastmodifiedby $policy.LastModifiedBy -ExchangeLocation (($policy.exchangelocation.name)-join ';') -SharePointLocation (($policy.sharePointlocation.name)-join ';') -ContentMatchQuery $rule.ContentMatchQuery -holdcreatedtime $policy.WhenCreatedUTC -holdchangedtime $policy.WhenChangedUTC
    }
    }
    }
    " "
    Write-host "Script complete! Report file: '$outputPath'"
    " "
    #script end
  2. In the Windows PowerShell session that opened in Step 1, go to the folder where you saved the script.

  3. Run the script; for example:

    .\CaseHoldsReport.ps1

    The script will prompt for a target folder to save the report to.

  4. Type the full path name of the folder to save the report to, and then press Enter.

    Tip: To save the report in the same folder that the script is located in, type a period (".") when prompted for a target folder. To save the report in a subfolder in the folder where the script is located, just type the name of the subfolder.

    The script starts to collect information about all the eDiscovery cases in your organization. Don't access the report file while the script is running. After the script is complete, a confirmation message is displayed in the Windows PowerShell session. After this message is displayed, you can access the report in the folder that you specified in Step 4. The file name for the report is CaseHoldsReport<DateTimeStamp>.csv.

    Here's an example of running the CaseHoldsReport.ps1 script.

    The output after running the CaseHoldsReport.ps1 script

Return to top

More information

The case holds report that's created when you run the script in this article contains the following information about each hold. As previously explained, you have to be an eDiscovery Administrator to return information for all holds in your organization. For more information about case holds, see Manage eDiscovery cases in the Office 365 Security & Compliance Center.

  • The name of the hold and the name of the eDiscovery case that the hold is associated with.

  • Whether or not the eDiscovery case is active or closed.

  • Whether or not the hold is enabled or disabled.

  • The members of the eDiscovery case that the hold is associated with. Case members can view or manage a case, depending on the eDiscovery permissions they've been assigned.

  • The time and date the case was created.

  • If a case is closed, the person who closed it and the time and date it was closed.

  • The Exchange mailboxes and SharePoint sites locations that are on hold.

  • If the hold is query-based, the query syntax.

  • The time and date the hold was created and the person who created it.

  • The time and date the hold was last changed and the person who changed it.

Return to top

Expand your skills
Explore training
Get new features first
Join Office Insiders

Was this information helpful?

Thank you for your feedback!

Thank you for your feedback! It sounds like it might be helpful to connect you to one of our Office support agents.

×