Create a report on holds in eDiscovery cases

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 the compliance center in Office 365 or Microsoft 365. 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. If there are cases that don't have any holds, the script will create an additional report with a list of cases without holds.

See the More information section for a detailed description of the information included in the report.

Admin requirements and script information

  • 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.

  • 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 PowerShell

The first step is to connect to Security & Compliance Center PowerShell for your organization. For step-by-step instructions, see Connect to Security & Compliance Center PowerShell.

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

After you've connected to Security & Compliance Center 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 "   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
    $Path = Read-Host 'Enter a file path to save the report to a .csv file'
    $outputpath=$Path+'\'+'CaseHoldsReport'+' '+$'-'+$time.month+'-'+$time.year+' '+$time.hour+'.'+$time.minute+'.csv'
    $noholdsfilepath=$Path+'\'+'CaseswithNoHolds'+' '+$'-'+$time.month+'-'+$time.year+' '+$time.hour+'.'+$time.minute+'.csv'
    #add case details to the csv file
    function add-tocasereport{
    $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 :" $
    if($cc.status -eq 'Closed')
    $cmembers = ((Get-ComplianceCaseMember -Case $ ';'
    add-tocasereport -casename $ -casestatus $cc.Status -caseclosedby $cc.closedby -caseClosedDateTime $cc.ClosedDateTime -casemembers $cmembers
    $cmembers = ((Get-ComplianceCaseMember -Case $ ';'
    $policies = Get-CaseHoldPolicy -Case $cc.Name | %{ Get-CaseHoldPolicy $_.Name -Case $_.CaseId -DistributionDetail}
    if ($policies -ne $NULL)
    foreach ($policy in $policies)
    $rule=Get-CaseHoldRule -Policy $
    add-tocasereport -casename $ -casemembers $cmembers -casestatus $cc.Status -casecreatedtime $cc.CreatedDateTime -holdname $ -holdenabled $policy.enabled -holdcreatedby $policy.CreatedBy -holdlastmodifiedby $policy.LastModifiedBy -ExchangeLocation (($ ';') -SharePointLocation (($ ';') -ContentMatchQuery $rule.ContentMatchQuery -holdcreatedtime $policy.WhenCreatedUTC -holdchangedtime $policy.WhenChangedUTC
    write-host "No hold policies found in case:" $ -foregroundColor 'Yellow'
    " "
    [string]$ | out-file -filepath $noholdsfilepath -append
    " "
    Write-host "Script complete! Report files saved to this folder: '$Path'"
    " "
    #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:


    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.


    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.

    Addtionally, the script also creates a report with a list of cases that don't have any holds. The file name for this report is CaseswithNoHolds<DateTimeStamp>.csv.

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

    The output after running the CaseHoldsReport.ps1 script

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 eDiscovery cases.

  • 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.