使用腳本在 eDiscovery 建立保留報告

此 PowerShell 腳本讓電子發現管理員與電子發現管理者能產生一份報告,包含所有與 Microsoft Purview 入口網站電子發現案件相關的保留資訊。 報告中包含如暫停所關聯案件名稱、暫停的內容位置,以及暫停是否基於查詢等資訊。 如果有些案件沒有保留,腳本會建立一份額外的報告,裡面有沒有保留的案件清單。

提示

立即開始使用 Microsoft Security Copilot,探索利用 AI 力量更聰明、更快速地工作的新方法。 在 Microsoft Purview 中了解更多關於 Microsoft Security Copilot 的資訊。

暫停報告的內容

本案報告指出本文所建立的腳本包含關於每個保留的以下資訊:

  • 保留的名稱以及該保留所關聯的電子發現案件名稱。
  • 該保留是否與電子發現案件相關。
  • 無論電子發現案件是否仍在進行中或已結案。
  • 不管是開啟還是關閉這個保留。
  • 與該保留案相關的電子發現案件成員。 案件成員可依據分配的電子發現權限查看或管理案件。
  • 案件成立的時間和日期。
  • 如果案件已經結案,則要記錄關閉該案件的人以及結案的時間和日期。
  • Exchange 信箱和 SharePoint 網站的位置都暫停了。
  • 如果 hold 是基於查詢的,則是查詢語法。
  • 預約建立的時間和日期,以及創建者。
  • 預約最後更改的時間和日期,以及更改日期的人。

管理員需求與腳本資訊

  • 要產生您組織內所有電子發現案件的報告,您必須是組織中的電子發現管理員。 如果您是電子發現經理,報告中僅包含您可以存取的案件資訊。 欲了解更多關於電子發現權限的資訊,請參閱「指派電子發現權限」。
  • CaseHoldsReport.ps1 腳本的錯誤處理極少。 其主要目的是快速建立一份關於您組織中電子發現案件所持有的暫停報告。

重要事項

在任何 Microsoft 標準支援程式或服務下,不支援本文中提供的範例指令碼。 範例指令碼係依「現狀」提供,不含任何種類的擔保方式。 Microsoft 另外不承擔任何明示或默示的擔保,包括但不限於適售性或適合某特定用途的默示擔保。 使用或操作範例指令碼和文件發生的所有風險,皆屬於您的責任。 Microsoft、其作者以及其他與建置、生產或交付程式碼相關的任何人在任何情況下皆完全不需對任何損失負責任,包括但不限於商業利潤損失、業務中斷、業務資訊損失、或其他錢財損失等因使用或無法使用範例指令碼或文件所發生的損失,即使 Microsoft 曾建議這些損失發生的可能性。

步驟 1︰連線至安全性與合規性 PowerShell

首先,連接貴組織的安全 & 合規 PowerShell。 如需逐步指示,請參閱連線到安全性與合規性 PowerShell。

步驟二:執行腳本以報告與電子發現案件相關的暫停

連接安全 & 合規 PowerShell 後,建立並執行收集組織內電子發現案件資訊的腳本。

  1. 請使用檔名.ps1CaseHoldsReport.ps1後綴 ;例如 ,將以下文字儲存到 Windows PowerShell 腳本檔中。

     #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
     $time = get-date -Format dd-MM-yyyy_hh.mm
     $Path = Read-Host 'Enter a folder path to save the report to a .csv file (filename is created automatically)'
     $outputpath = $Path + '\' + 'CaseHoldsReport' + ' ' + $time + '.csv'
     $noholdsfilepath = $Path + '\' + 'CaseswithNoHolds' + $time + '.csv'
    
     #add case details to the csv file
     function add-tocasereport {
         Param([string]$casename,
             [String]$casetype,
             [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,
             [string]$holdstatus,
             [string]$holderror
         )
    
         $addRow = New-Object PSObject
         Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Case name" -Value $casename
         Add-Member -InputObject $addRow -MemberType NoteProperty -Name "Case type" -Value $casetype
         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
         Add-Member -InputObject $addrow -MemberType NoteProperty -Name "Hold Status" -Value $holdstatus
         Add-Member -InputObject $addrow -MemberType NoteProperty -Name "Hold Error" -Value $holderror
    
         $allholdreport = $addRow | Select-Object "Case name", "Case type", "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)", "Hold Status", "Hold Error"
         $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 eDiscovery 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 -casetype $cc.casetype -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 }
             if ($policies -ne $NULL) {
                 foreach ($policy in $policies) {
                     $rule = Get-CaseHoldRule -Policy $policy.name
                     add-tocasereport -casename $cc.name -casetype $cc.casetype -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 -holdstatus $policy.DistributionStatus -holderror $policy.DistributionResults
                 }
             }
             else {
                 Write-Host "No hold policies found in case:" $cc.name -foregroundColor 'Yellow'
                 " "
                 [string]$cc.name | out-file -filepath $noholdsfilepath -append
             }
         }
     }
    
     #get information on the cases and pass values to the case report function
     " "
     write-host "Gathering a list of eDiscovery cases and holds..."
     " "
     $edc = Get-ComplianceCase -CaseType Advanced -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 -casetype $cc.casetype -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 }
             if ($policies -ne $NULL) {
                 foreach ($policy in $policies) {
                     $rule = Get-CaseHoldRule -Policy $policy.name
                     add-tocasereport -casename $cc.name -casetype $cc.casetype -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 -holdstatus $policy.DistributionStatus -holderror $policy.DistributionResults
    
                 }
             }
             else {
                 write-host "No hold policies found in case:" $cc.name -foregroundColor 'Yellow'
                 " "
                 [string]$cc.name | out-file -filepath $noholdsfilepath -append
             }
         }
     }
    
     " "
     Write-host "Script complete! Report files saved to this folder: '$Path'"
     " "
     #script end
    
  2. 在步驟 1 開啟的 Windows PowerShell 會話中,前往你儲存腳本的資料夾。

  3. 執行劇本;例如:

    .\CaseHoldsReport.ps1
    

    腳本會提示一個目標資料夾來儲存報告。

  4. 輸入儲存報告資料夾的完整路徑名稱,然後按下 Enter。

    提示

    要將報告儲存在腳本所在的同一資料夾,請輸入句號 (“。) 在提示輸入目標資料夾時。 要將報告儲存在腳本所在資料夾的子資料夾,只需輸入子資料夾名稱即可。

    腳本會開始收集你組織內所有電子發現案件的資訊。 腳本執行時不要存取報告檔。 腳本完成後,Windows PowerShell 會階段顯示確認訊息。 此訊息顯示後,您可以在提示指定目標資料夾時,存取該報告。 該報告的檔案名稱為 CaseHoldsReport<DateTimeStamp>.csv。

    此外,腳本會建立一份報告,列出沒有保留的案件。 此報告的檔案名稱為 CaseswithNoHolds<DateTimeStamp>.csv。

    這裡有一個執行 CaseHoldsReport.ps1 腳本的範例。

    PowerShell 主控台的截圖顯示 CaseHoldsReport.ps1 腳本輸出,列出 eDiscovery 案件保留的結果。