PowerShell Get-RetentionCompliancePolicyで場所設定が反映されない原因と対策|-DistributionDetailで保持ポリシーを正確に確認

Microsoft Purview の保持ポリシー(Retention Compliance Policy)を PowerShell で点検すると、UI で Exchange をオフにしているのに Get-RetentionCompliancePolicy の結果だけでは判断できず「反映されていない?」と感じることがあります。原因はコマンドの既定出力が“概要”である点にあり、正しい見方を知ると一気に解決します。

目次

起きていること:UI と PowerShell の見え方がズレる

保持ポリシーの運用を自動化していると、次のような場面に出会いがちです。

  • Microsoft Purview のポータル(Data Lifecycle Management など)では「Exchange の場所:オフ」になっている
  • ところが PowerShell で Get-RetentionCompliancePolicy を実行しても、Exchange の有効/無効を示すような分かりやすい値が出ない
  • ExchangeLocation などの Location 系プロパティが {} に見えたり、そもそも表示に出てこなかったりして混乱する

結論から言うと、“場所設定が反映されていない”のではなく、“見ている出力がサマリー表示で詳細が省略されている”ケースが大半です。

原因:Get-RetentionCompliancePolicy の既定出力は「概要」

Get-RetentionCompliancePolicy は、オプションを付けない既定の状態だとサマリー(概要)を返します。Microsoft Learn の説明でも、既定表示ではポリシー名や Enabled などの概要項目が中心であることが明示されています。

さらに重要なのが、-DistributionDetail を付けない場合、DistributionStatus*Location プロパティの値は不正確になり得る、という注意書きです。つまり、Location を頼りに「Exchange がオン/オフ」と断定すると誤判定になりやすい、ということです。

「Workload 列がいつも同じ」に見えるのも仕様

既定出力の Workload についても、現場では混乱ポイントになります。Microsoft Learn では、Workload は“現在は全ワークロードを表示する(Exchange / SharePoint / OneDrive / Skype / ModernGroup など)”と説明されており、実際にどのワークロードに適用されているかを示すものではない旨が書かれています。

このため、「Workload が全部出ているのに Exchange をオフにしても変化しない」=「設定が効いてない」と見えてしまいますが、ここも既定表示の性格によるものです。

解決策:-DistributionDetail を付けて“正しい Location”を取得する

場所(Location)の有効/無効や対象範囲を正しく見たいなら、実質的に-DistributionDetail は必須です。このスイッチを付けると、DistributionResults に配布の詳細が入り、*Location プロパティも正確な値が取得できると説明されています。

まずは、最小構成で「そのポリシーの Location をまとめて確認」する例です。

Get-RetentionCompliancePolicy -Identity "My Policy Name" -DistributionDetail |
  Format-List Name, Enabled, Mode,
              ExchangeLocation, ExchangeLocationException,
              SharePointLocation, SharePointLocationException,
              OneDriveLocation, OneDriveLocationException,
              ModernGroupLocation, ModernGroupLocationException,
              TeamsChannelLocation, TeamsChannelLocationException,
              TeamsChatLocation, TeamsChatLocationException,
              SkypeLocation

※表示したい Location は環境(ポリシー種別)によって増減します。まずは Format-List * で一度フル表示し、実在するプロパティだけに絞ると事故が減ります。

Location プロパティの読み方

-DistributionDetail を付けたうえで、よく出会う値のパターンを整理します。

見え方(例)意味(実務的な解釈)よくある UI 側の状態
ExchangeLocation = {All}Exchange を全体対象として有効化Exchange の場所がオン(全体)
ExchangeLocation = {user1, user2, ...}Exchange を特定対象で有効化(静的スコープ)Exchange の場所がオン(対象指定)
ExchangeLocation = {}Exchange の対象が存在しない(オフ/未設定)Exchange の場所がオフ
*LocationException = {userA, ...}例外(除外)として指定されている対象「除外」リストに追加済み

ポイントは、-DistributionDetail なしの {} は“正しい空”とは限らないことです。まずは必ず -DistributionDetail で取り直してから判定してください。

まずここから:Security & Compliance PowerShell に正しく接続する

Get-RetentionCompliancePolicy は、通常の Exchange Online PowerShell とは別枠のSecurity & Compliance PowerShell 側で利用するコマンドです。Microsoft Learn でも「この cmdlet は Security & Compliance PowerShell でのみ利用可能」と明記されています。

接続の流れは次の通りです(対話サインインの例)。

  1. Exchange Online PowerShell モジュールを読み込む
  2. Connect-IPPSSession で Security & Compliance PowerShell に接続する
  3. 終わったら Disconnect-ExchangeOnline で切断する
# モジュールの読み込み
Import-Module ExchangeOnlineManagement

# Security & Compliance PowerShell へ接続
Connect-IPPSSession -UserPrincipalName [email protected]

# 動作確認(ここで Get-RetentionCompliancePolicy が実行できればOK)
Get-RetentionCompliancePolicy

# 切断
Disconnect-ExchangeOnline -Confirm:$false

接続手順や注意点(環境ごとの接続先 URI、PowerShell 7 の挙動など)は Microsoft Learn の「Connect to Security & Compliance PowerShell」にまとまっています。

実務で効く:ON/OFF をレポート形式に正規化するサンプル

運用で困るのは、「Location の生値」を見ても人間がすぐ判断できないことです。そこで、{All} / {} / リスト指定をざっくり正規化して、監査・棚卸しに使える形にする例を載せます。

function Get-RetentionPolicyLocationSummary {
    param(
        [Parameter(Mandatory)]
        [string]$Identity
    )

    $p = Get-RetentionCompliancePolicy -Identity $Identity -DistributionDetail

    function NormalizeLocation($value) {
        if ($null -eq $value) { return "N/A" }
        if ($value.Count -eq 0) { return "OFF/Empty" }
        if ($value.Count -eq 1 -and $value[0].ToString() -eq "All") { return "ON (All)" }
        return "ON (Static: $($value.Count) items)"
    }

    [pscustomobject]@{
        Name      = $p.Name
        Enabled   = $p.Enabled
        Mode      = $p.Mode

        Exchange  = NormalizeLocation $p.ExchangeLocation
        EX_Except = ($p.ExchangeLocationException | Measure-Object).Count

        SharePoint  = NormalizeLocation $p.SharePointLocation
        SPO_Except  = ($p.SharePointLocationException | Measure-Object).Count

        OneDrive    = NormalizeLocation $p.OneDriveLocation
        OD_Except   = ($p.OneDriveLocationException | Measure-Object).Count

        M365Group   = NormalizeLocation $p.ModernGroupLocation
        GroupExcept = ($p.ModernGroupLocationException | Measure-Object).Count

        TeamsChannel = NormalizeLocation $p.TeamsChannelLocation
        TeamsChat    = NormalizeLocation $p.TeamsChatLocation
    }
}

Get-RetentionPolicyLocationSummary -Identity "My Policy Name" | Format-List

この形にしておくと、「Exchange が ON/All なのに例外が多すぎる」「OneDrive が OFF のはずが ON になっている」などが棚卸しで一目で分かります。

対象一覧が長いときの“切れ対策”

ExchangeLocation などが大量だと、画面表示では途中で見づらくなります。実務では次のようにCSV/JSON に落として確認すると確実です。

$p = Get-RetentionCompliancePolicy -Identity "My Policy Name" -DistributionDetail

# Exchange の対象だけをテキスト化して保存(見やすい)
$p.ExchangeLocation | Out-File -FilePath ".\ExchangeLocation.txt" -Encoding utf8

# 例外も保存
$p.ExchangeLocationException | Out-File -FilePath ".\ExchangeLocationException.txt" -Encoding utf8

# 深い階層が混ざる場合は JSON(Depth を上げる)
$p | ConvertTo-Json -Depth 10 | Out-File -FilePath ".\PolicyDetail.json" -Encoding utf8

「設定は正しいのに効いていない?」を切り分ける:配布状況の確認

Location が正しく取れても、現場では次の二択で悩みます。

  • ポリシーの場所設定は正しい(= 期待通りの Location が出ている)
  • しかし、配布(sync/distribution)が終わっておらず、対象側に反映されていない

この切り分けに使うのが DistributionResults です。Microsoft のトラブルシューティング記事でも、ポリシーのエラー内容は -DistributionDetail を付けて DistributionResults を展開して確認する流れが示されています。

Get-RetentionCompliancePolicy -Identity "My Policy Name" -DistributionDetail |
  Select-Object -ExpandProperty DistributionResults

代表的なエラーと対処の方向性

DistributionResults には、例えば以下のような状態が出ます(名称は例で、環境により複数出ます)。Microsoft Learn の解決手順では、エラー内容ごとに「場所の重複を消す」「サイト容量を確保する」「Retry する」などの具体策が案内されています。

DistributionResults に出がちな例意味のイメージまずやること
MultipleInactiveRecipientsError指定した場所が一意に解決できない重複している場所指定を整理し、再配布
SiteOutOfQuota対象サイトの容量不足容量を増やす/不要データ削除 → 再配布
PolicySyncTimeout同期が時間内に完了しない時間を置く/RetryDistribution
ActiveDirectorySyncErrorMicrosoft Entra ID 同期に失敗再試行(Retry)、必要ならサポート調査

再配布(RetryDistribution)の実行例

PowerShell 側で「再配布」を明示的にかけたい場合、Microsoft の手順でも Set-RetentionCompliancePolicy-RetryDistribution が案内されています。

Set-RetentionCompliancePolicy -Identity "My Policy Name" -RetryDistribution

また、Set-RetentionCompliancePolicy 自体は“組織全体のフル同期を引き起こす大きな操作”であり、次の更新は配布が成功してから行うのが推奨されています。自動化では特に連続実行しない設計が安全です。

ルールを確認したい:Get-RetentionComplianceRule で保持期間・動作を読む

保持ポリシーは「どこに適用するか(Location)」と「何をするか(Rule)」がセットです。Location が正しく見えても、実際の保持期間や削除動作が期待通りかはルール側を見ないと分かりません。

ルールは Get-RetentionComplianceRule で確認します。Microsoft Learn の構文では -Policy パラメーターでポリシーに紐づくルールを絞り込めます。

Get-RetentionComplianceRule -Policy "My Policy Name" | Format-List *

よく確認する観点は次の通りです(プロパティ名は環境やルール種別で差が出るため、まず Format-List * で把握してください)。

  • 保持アクション:保持のみ/削除のみ/保持後に削除
  • 保持期間:日数(例:3650 日=10年)、または Unlimited
  • 期限日の基準:作成日基準か、更新日基準か
  • 条件:KQL(ContentMatchQuery)などで対象を絞っているか

保持アクションと保持期間を“言語化”する

ルールの編集コマンドである Set-RetentionComplianceRule のパラメーターを見ると、保持期間や保持動作がどの名前で扱われるかが分かります。たとえば、保持動作は RetentionComplianceAction、保持期間は RetentionDuration で指定し、アクションは Delete/Keep/KeepAndDelete が定義されています。

項目PowerShell(例)意味
保持アクションRetentionComplianceAction = Keep保持のみ(削除はしない)
保持アクションRetentionComplianceAction = Delete削除のみ(一定期間後に削除)
保持アクションRetentionComplianceAction = KeepAndDelete一定期間保持し、その後削除
保持期間RetentionDuration = 180180 日保持(単位は日)
保持期間RetentionDuration = Unlimited無期限(削除しない/永続保持)

制限と運用設計:静的スコープの上限を先に知っておく

「コマンドの制限はある?」という疑問に対して、実務で効くのは静的スコープ(手で対象を列挙する方式)の上限です。Microsoft Learn の上限ドキュメントでは、静的スコープで “特定のユーザー/グループ/サイトを含める・除外する” 場合の上限が workload 別に整理されています。

対象(静的スコープ)1ポリシーあたりの最大数設計上の注意
Exchange メールボックス1,000人事異動や入退社で増減が多いなら、アダプティブ スコープも検討
Microsoft 365 グループ500部署・プロジェクトでグループが増える組織は分割設計が必要になりやすい
Teams チャネル メッセージ1,000対象チームが多い場合はスコープ設計を最初に固める
Teams チャット メッセージ1,000ユーザー個別指定の運用は上限到達が早い
SharePoint サイト100特定サイトを個別指定する設計はポリシー数が増えやすい
OneDrive アカウント100個別指定が多いなら、アダプティブ スコープやルール再設計を検討

上限を超えそうな場合の現実解は次のどちらかです。

  • ポリシーを分割して、同じ保持設定を複数ポリシーで配る(上限は“ポリシー単位”)
  • アダプティブ スコープ(属性ベースの動的スコープ)を検討して、対象の増減を運用で吸収する

なお、テナント全体のポリシー数にも上限があり、Exchange/SharePoint/OneDrive のワークロード別に最大値が整理されています(例:Exchange の上限 1,800 など)。大量運用している組織では、棚卸し時に一度確認しておくと安心です。

よくある落とし穴と、早く抜けるチェックリスト

Location を見たのに UI と合わない

  • -DistributionDetail を付け忘れていないか(最優先)
  • そもそも Security & Compliance PowerShell に接続できているか(別セッションで実行していないか)
  • 配布が終わっていない/エラーで止まっていないか(DistributionResults を展開)

Teams の保持ポリシーだけ一覧したい

Get-RetentionCompliancePolicy には Teams のみを返すスイッチ(-TeamsPolicyOnly)や Teams を除外するスイッチ(-ExcludeTeamsPolicy)があります。Teams 関連の棚卸しでは、ポリシー一覧が膨らむテナントほど効きます。

# Teams のみ
Get-RetentionCompliancePolicy -TeamsPolicyOnly

# Teams を除外
Get-RetentionCompliancePolicy -ExcludeTeamsPolicy

ルールがあるのに “無い”ように見える

ポリシー側で「ルール種別」まで確認したい場合、-RetentionRuleTypes スイッチが必要です。付けない場合、RetentionRuleTypes が空に見えたり HasRules が False に見えたりすることがある、と Microsoft Learn で説明されています。

Get-RetentionCompliancePolicy -RetentionRuleTypes |
  Format-Table -Auto Name, RetentionRuleTypes

まとめ:場所設定が見えないときは “仕様のサマリー表示” を疑う

  • Get-RetentionCompliancePolicy の既定出力は概要で、Location の値は不正確になり得る
  • 場所(Exchange/SharePoint/OneDrive/Teams など)の ON/OFF を確認したいなら -DistributionDetail が必須
  • 配布状況やエラーは DistributionResults を展開して確認し、必要なら -RetryDistribution を使う
  • 保持期間や動作は Get-RetentionComplianceRule -Policy でルールを確認する
  • 静的スコープには上限があるため、増え続ける対象は分割やアダプティブ スコープを前提に設計する

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次