From c6225ec5b7473b3ec14a30c3e1a0dad60424ac75 Mon Sep 17 00:00:00 2001 From: Anirudh Date: Thu, 18 Dec 2025 16:13:32 -0800 Subject: [PATCH 1/9] Create Get-AdaptiveScopeMembers.md Documentation for new cmdlet Get-AdaptiveScopeMembers in Security & Compliance powershell --- .../Get-AdaptiveScopeMembers.md | 405 ++++++++++++++++++ 1 file changed, 405 insertions(+) create mode 100644 exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md diff --git a/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md b/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md new file mode 100644 index 0000000000..24d07f83bc --- /dev/null +++ b/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md @@ -0,0 +1,405 @@ +--- +applicable: Exchange Online, Security & Compliance +author: anirudhbharadwaj +external help file: Microsoft.Exchange.TransportMailflow-Help.xml +Locale: en-US +Module Name: ExchangePowerShell +ms.author: anirudhbharadwaj +online version: https://learn.microsoft.com/powershell/module/exchangepowershell/get-adaptivescopemembers +schema: 2.0.0 +title: Get-AdaptiveScopeMembers +--- + +# Get-AdaptiveScopeMembers + +## SYNOPSIS +This cmdlet is available only in the cloud-based service. + +Use the Get-AdaptiveScopeMembers cmdlet to retrieve current and past members of adaptive scopes in your organization. Adaptive scopes are used in retention policies, Insider Risk Management policies and retention label policies. + +For information about the parameter sets in the Syntax section below, see [Exchange cmdlet syntax](https://learn.microsoft.com/powershell/exchange/exchange-cmdlet-syntax). + +## SYNTAX + +### Identity (Default) + +``` +Get-AdaptiveScopeMembers [-Identity] [] +``` + +### Default + +``` +Get-AdaptiveScopeMembers [-Identity] + [-AdaptiveReportFilters ] + [-PageResultSize ] + [-State ] + [] +``` + +### AdaptiveReportPagination + +``` +Get-AdaptiveScopeMembers [-Identity] -PageCookie [] +``` + +## DESCRIPTION + +Use this cmdlet to retrieve existing and past members (users, groups, or sites) of an adaptive scope. + +The cmdlet returns a list where: +- The **first element** contains **result metadata**, and +- The **subsequent elements** contain the **members**. + +The metadata includes: +- The **total number of members** for the request, +- The **number of members returned in the current page**, and +- Whether **additional pages** are available. + +If additional pages exist, the metadata will include a **`Watermark`** value and **`IsLastPage`** will be `false`. +To retrieve the next page, pass the `Watermark` value to the **`-PageCookie`** parameter in your next invocation of the cmdlet. +Use the **`-AdaptiveReportFilters`** parameter to filter the members. + +To use this cmdlet in Security & Compliance PowerShell, you need to be assigned permissions. For more information, see [Permissions in the Microsoft Purview compliance portal](https://learn.microsoft.com/purview/microsoft-365-compliance-center-permissions). + +## EXAMPLES + +### Example 1 - Retrieve members of an adaptive scope with default page size of 10000 +```powershell +Get-AdaptiveScopeMembers -Identity "US Finance Users" +``` + +This example retrieves the members of the adaptive scope US Finance Users. +If the scope contains fewer than 10,000 members, all members are returned. +For larger scopes, only the first 10,000 members are included, and the first object in the response contains metadata with a watermark that can be used to request subsequent pages. + +### Example 2 - Retrieve all members of an adaptive scope +```powershell +Get-AdaptiveScopeMembers -Identity "US Finance Users" -PageResultSize unlimited +``` + +This example returns every member of the adaptive scope US Finance Users. + +> **⚠️ Warning:** +> Although you *can* specify `Unlimited` to retrieve all members in a single request, this is **not recommended** for large adaptive scopes. Using `Unlimited` may lead to long‑running requests and increases the likelihood of transient failures that cannot be efficiently retried. + +### Example 3 - Retrieve only the count of members in the adaptive scope +```powershell +Get-AdaptiveScopeMembers -Identity "US Finance Users" -PageResultSize 0 +``` + +This example only returns the metadata with total member count of the adaptive scope US Finance Users. + + +### Example 4 - Retrieve up to 30 members of the adaptive scope +```powershell +Get-AdaptiveScopeMembers -Identity "US Finance Users" -PageResultSize 30 +``` + +This example retrieves the members of the adaptive scope US Finance Users. +If the scope contains fewer than 30 members, all members are returned. +For larger scopes, only the first 30 members are included, and the first object in the response contains metadata with a watermark that can be used to request subsequent pages. + +### Example 5 - Retrieve only the current members of the adaptive scope +```powershell +Get-AdaptiveScopeMembers -Identity "US Finance Users" -State Added +``` + +This example retrieves the current members of the adaptive scope US Finance Users. +If the scope contains fewer than 10,000 current members, all current members are returned. +For larger scopes, only the first 10,000 current members are included, and the first object in the response contains metadata with a watermark that can be used to request subsequent pages. + +### Example 6 - Retrieve only the past members of the adaptive scope +```powershell +Get-AdaptiveScopeMembers -Identity "US Finance Users" -State Removed +``` + +This example retrieves the past members of the adaptive scope US Finance Users. +If the scope contains fewer than 10,000 past members, all past members are returned. +For larger scopes, only the first 10,000 past members are included, and the first object in the response contains metadata with a watermark that can be used to request subsequent pages. + +### Example 7 - Retrieve a subset of members using filters +```powershell +Get-AdaptiveScopeMembers -Identity "US Finance Sites" -AdaptivereportFilters @{"SiteUrlContainsAny" = @("/personal/", "/teams/")} +``` + +This example retrieves the members of the adaptive scope US Finance Sites where the site url contains `/personal/` or `/teams/` +If the results contains fewer than 10,000 members, all are returned. +For larger results, only the first 10,000 are included, and the first object in the response contains metadata with a watermark that can be used to request subsequent pages. + +You can find more details about `AdaptiveReportFilters` in the [parameters section](#-AdaptiveReportFilters) + + +### Example 8 — Paginated results + +```powershell +$scope="US Finance Users"; $size=200; $cookie=$null +$all=@() +do { + $page = Get-AdaptiveScopeMembers -Identity $scope -Size $size -PageCookie $cookie + if(-not $page){ break } + $meta = $page[0] + if($meta.CurrentPageMemberCount -gt 0){ $all += $page[1..($page.Count-1)] } + $cookie = if($meta.IsLastPage){ $null } else { $meta.Watermark } +} while($cookie -ne $null) +$all | Export-Csv -NoTypeInformation -Path "D:\AdaptiveScopeMembers_$($scope -replace ' ','_').csv" +``` + +This example retrieves the members of the adaptive scope US Finance Users 200 members at a time and saves them to a list. +After all members are returned, it saves the list of members as a csv file. + + +## PARAMETERS + +### -Identity + +> Applicable: Exchange Online, Security & Compliance + +The Identity parameter specifies the adaptive scope. You can use any value that uniquely identifies the adaptive scope. For example: + +- Name +- Distinguished name (DN) +- GUID + +```yaml +Type: ComplianceRuleIdParameter +Parameter Sets: (All) +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByPropertyName, ByValue) +Accept wildcard characters: False +``` + +### -AdaptiveReportFilters + +> Applicable: Exchange Online, Security & Compliance + + +Specifies one or more filters used to refine the results returned by `Get-AdaptiveScopeMembers`. + +This parameter accepts a **PSWS hashtable**, where each key maps to a list (array) of **up to 10 values**. +Filters whose name contains **`Not`** act as exclusion filters and are typically **intersected** with other filters when multiple keys are provided. + +#### Supported Filter Keys +**Mailbox GUID filters** + +- `MailboxGuidEqualsAny` +- `MailboxGuidNotEqualsAny` + +**SMTP address filters** + +- `SmtpAddressEqualsAny` +- `SmtpAddressNotEqualsAny` +- `SmtpAddressStartsWithAny` +- `SmtpAddressNotStartsWithAny` + +**ObjectId filters** + +- `ObjectIdEqualsAny` +- `ObjectIdNotEqualsAny` + +**SharePoint Site filters** + +- `SiteIdEqualsAny` +- `SiteIdNotEqualsAny` +- `SiteUrlEqualsAny` +- `SiteUrlNotEqualsAny` +- `SiteUrlContainsAny` +- `SiteUrlNotContainsAny` +- `SiteUrlStartsWithAny` +- `SiteUrlNotStartsWithAny` + +**User Principal Name (UPN) filters** + +- `UpnEqualsAny` +- `UpnNotEqualsAny` +- `UpnStartsWithAny` +- `UpnNotStartsWithAny` + + +#### Example 1 — Filter by UPN prefix +```powershell +-AdaptiveReportFilters @{ + UpnStartsWithAny = @("john", "mary") +} +``` + +#### Example 2 — Include by SMTP address and exclude by UPN +```powershell +-AdaptiveReportFilters @{ + SmtpAddressEqualsAny = @("alice@contoso.com","bob@contoso.com") + UpnNotEqualsAny = @("bob.old@contoso.com") +} +``` + +#### Example 3 — Include by SMTP address or include by UPN +```powershell +-AdaptiveReportFilters @{ + SmtpAddressEqualsAny = @("alice@contoso.com","bob@contoso.com") + UpnEqualsAny = @("bob.old@contoso.com") +} +``` + + +```yaml +Type: PswsHashtable +Parameter Sets: Default +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PageCookie + +> Applicable: Exchange Online, Security & Compliance + +Specifies the bookmark from which the cmdlet should continue retrieving results. + +Use the **`Watermark`** value returned from a previous request to the *same* adaptive scope as the value of this parameter. The watermark acts as a continuation token, allowing the cmdlet to resume exactly where the previous page ended and fetch the next page of members. + +> **⚠️ Warning:** +> Do **not** manually edit or fabricate a watermark value. Doing so may cause skipped pages, duplicate results, or invalid requests. Always use the watermark exactly as returned by the cmdlet. + + +```yaml +Type: string +Parameter Sets: AdaptiveReportPagination +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PageResultSize + +> Applicable: Exchange Online, Security & Compliance + +Specifies the maximum number of members to return for the request. + +> **⚠️ Warning:** +> Although you *can* specify `Unlimited` to retrieve all members in a single request, this is **not recommended** for large adaptive scopes. Using `Unlimited` may lead to long‑running requests and increases the likelihood of transient failures that cannot be efficiently retried. + + +For best reliability and performance, retrieve members in **multiple smaller pages** until the last page is reached. This approach introduces natural breakpoints, reduces wait times, and allows seamless retries when transient issues occur. + + +```yaml +Type: UnlimitedInt +Parameter Sets: Default +Aliases: + +Required: False +Position: Named +Default value: 10000 +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -State + +> Applicable: Exchange Online, Security & Compliance + +The LocationState parameter specifies the state of the members of the adaptive scope. Valid values are: + +- Added +- Removed + +State Added specifies members which are current members of the adaptive scope. +State Removed specifies members which were once active members but have since been removed from membership. + +```yaml +Type: LocationState +Parameter Sets: Default +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](https://go.microsoft.com/fwlink/p/?LinkID=113216). + + +## Export to files + +### Description + +Customers often need to export all members of an adaptive scope into files for review, auditing, offline analysis, or to share with other teams. +The **Export‑AdaptiveScopeMembers** helper script simplifies this process by automatically paging through the scope, exporting each page to a CSV file, and writing execution metadata for resume. + +This export workflow is **restartable**. +If the script stops midway due to a transient failure, network issue, or timeout, you can simply run it again. It will read the existing metadata file, resume from the last successfully processed page, and continue exporting until all pages have been retrieved. + +### Usage + +Paste the following PowerShell function into your session and call it with the desired parameters. + + +``` +function Export-AdaptiveScopeMembers { + [CmdletBinding()] param([string]$Scope,[string]$Out,[int]$Size=10000,[bool]$Resume=$true) + $scope=$Scope; $out=$Out; $size=$Size; + $meta=Join-Path $out "$scope-exportadaptivescopemembersexecutioninfo.json" + if (-not (Test-Path $out)) { New-Item -ItemType Directory -Path $out | Out-Null } + $m = if ($resume -and (Test-Path $meta)) { Get-Content $meta -Raw | ConvertFrom-Json } else {$null} + $cookie = if ($m) {$m.Watermark} else {$null}; $page = if ($m -and $m.IsLastPage -ne $true) { $m.LastPageProcessed + 1 } else {1}; $isLast=$false + do { + $res = if ($cookie) { Get-AdaptiveScopeMembers -Identity $scope -PageCookie $cookie -WarningAction SilentlyContinue} else { Get-AdaptiveScopeMembers -Identity $scope -PageResultSize $size -WarningAction SilentlyContinue } + $metaObj = $res[0]; $members = $res[1..($res.Count-1)] + if ($members.Count) { $file=Join-Path $out "$scope-part$($page).csv"; $members | Export-Csv $file -NoTypeInformation; Write-Host "Exported $($members.Count) of page $page to file '$file'" } + $cookie = $metaObj.Watermark; $isLast = $metaObj.IsLastPage + $status = @{TimestampUtc=(Get-Date).ToUniversalTime().ToString("o"); TotalResults=$metaObj.TotalMemberCount; PageSize=$metaObj.CurrentPageMemberCount; Identity=$metaObj.Identity; Watermark=$cookie; LastPageProcessed=$page; IsLastPage=$metaObj.IsLastPage} + if ($isLast) { + $status = @{TimestampUtc=(Get-Date).ToUniversalTime().ToString("o"); TotalResults=$metaObj.TotalMemberCount; Identity=$metaObj.Identity; Watermark=$cookie; LastPageProcessed=$page; IsLastPage=$metaObj.IsLastPage} + } + $status | ConvertTo-Json | Set-Content $meta + $page++ + } while (-not $isLast) + Write-Host "Completed exporting members of adaptive scope '$scope' to folder '$out'" +} +``` + +Users can now call `Export-AdaptiveScopeMembers` to save the results to files in their disk + +### Example 1 +```powershell +Export-AdaptiveScopeMembers -Scope "US Finance Users" -Out "D:\adaptivescopedetails" +``` + +This example retrieves the members of the adaptive scope US Finance Users and saves every 10000 members to a csv file under the provided folder. The folder is created if it doesn't already exist. + +### Example 2 +```powershell +Export-AdaptiveScopeMembers -Scope "US Finance Users" -Out "D:\adaptivescopedetails" -Size 200 +``` + +This example retrieves the members of the adaptive scope US Finance Users and saves every 200 members to a csv file under the provided folder. The folder is created if it doesn't already exist. + +### Example 3 +```powershell +Export-AdaptiveScopeMembers -Scope "US Finance Users" -Out "D:\adaptivescopedetails" -Size 200 -Resume $false +``` + +By default, the -Resume parameter is set to $true, allowing the export process to automatically continue from the last completed page if a PowerShell session is interrupted. +Specify $false to start the export from the beginning and overwrite any previously saved progress. + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS From 8912acf2b83e837fbf4ef56c9a6989ddb3fafd19 Mon Sep 17 00:00:00 2001 From: Anirudh Date: Thu, 18 Dec 2025 16:41:01 -0800 Subject: [PATCH 2/9] Update serviceMapping.json Add service mapping for Get-AdaptiveScopeMembers cmdlet --- exchange/mapping/serviceMapping.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exchange/mapping/serviceMapping.json b/exchange/mapping/serviceMapping.json index 7127c4c535..09f7bb19bf 100644 --- a/exchange/mapping/serviceMapping.json +++ b/exchange/mapping/serviceMapping.json @@ -1056,6 +1056,7 @@ "Export-ContentExplorerData": "policy-and-compliance-retention", "Export-FilePlanProperty": "policy-and-compliance-retention", "Get-AdaptiveScope": "policy-and-compliance-retention", + "Get-AdaptiveScopeMembers": "policy-and-compliance-retention", "Get-AppRetentionCompliancePolicy": "policy-and-compliance-retention", "Get-AppRetentionComplianceRule": "policy-and-compliance-retention", "Get-ComplianceRetentionEvent": "policy-and-compliance-retention", @@ -1418,4 +1419,4 @@ "Undo-SoftDeletedUnifiedGroup": "users-and-groups", "Update-DistributionGroupMember": "users-and-groups", "Upgrade-DistributionGroup": "users-and-groups" -} \ No newline at end of file +} From 6f8075154164c4479e089fd4fb948ceaac901f4a Mon Sep 17 00:00:00 2001 From: Anirudh Date: Thu, 18 Dec 2025 16:42:41 -0800 Subject: [PATCH 3/9] Update ExchangePowerShell.md Add toc for Get-AdaptiveScopeMembers cmdlet --- exchange/exchange-ps/ExchangePowerShell/ExchangePowerShell.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/exchange/exchange-ps/ExchangePowerShell/ExchangePowerShell.md b/exchange/exchange-ps/ExchangePowerShell/ExchangePowerShell.md index 79d36f8a44..e190ada99d 100644 --- a/exchange/exchange-ps/ExchangePowerShell/ExchangePowerShell.md +++ b/exchange/exchange-ps/ExchangePowerShell/ExchangePowerShell.md @@ -2159,6 +2159,8 @@ Exchange PowerShell is built on PowerShell technology to a powerful command-line ### [Get-AdaptiveScope](Get-AdaptiveScope.md) +### [Get-AdaptiveScopeMembers](Get-AdaptiveScopeMembers.md) + ### [Get-AppRetentionCompliancePolicy](Get-AppRetentionCompliancePolicy.md) ### [Get-AppRetentionComplianceRule](Get-AppRetentionComplianceRule.md) From 7a6409de768171d75402e20a57a2b4e063c8b42c Mon Sep 17 00:00:00 2001 From: Anirudh Date: Thu, 18 Dec 2025 16:43:55 -0800 Subject: [PATCH 4/9] Update .openpublishing.redirection.exchange.json Add entry for Get-AdaptiveScopeMembers --- .openpublishing.redirection.exchange.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.openpublishing.redirection.exchange.json b/.openpublishing.redirection.exchange.json index e13a297239..a907bcaba7 100644 --- a/.openpublishing.redirection.exchange.json +++ b/.openpublishing.redirection.exchange.json @@ -7995,6 +7995,11 @@ "redirect_url": "/powershell/module/exchangepowershell/get-adaptivescope", "redirect_document_id": true }, + { + "source_path": "exchange/virtual-folder/exchange/Get-AdaptiveScopeMembers.md", + "redirect_url": "/powershell/module/exchangepowershell/get-adaptivescopemembers", + "redirect_document_id": true + }, { "source_path": "exchange/virtual-folder/exchange/Get-AddressBookPolicy.md", "redirect_url": "/powershell/module/exchangepowershell/get-addressbookpolicy", From ed0f0a1c07d552b02311feaa25da4bf2349aea1b Mon Sep 17 00:00:00 2001 From: Anirudh Date: Thu, 18 Dec 2025 16:46:34 -0800 Subject: [PATCH 5/9] Update Get-AdaptiveScopeMembers.md change author to microsoft alias --- .../ExchangePowerShell/Get-AdaptiveScopeMembers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md b/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md index 24d07f83bc..37d884b1fd 100644 --- a/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md +++ b/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md @@ -1,10 +1,10 @@ --- applicable: Exchange Online, Security & Compliance -author: anirudhbharadwaj +author: amuralidhara external help file: Microsoft.Exchange.TransportMailflow-Help.xml Locale: en-US Module Name: ExchangePowerShell -ms.author: anirudhbharadwaj +ms.author: amuralidhara online version: https://learn.microsoft.com/powershell/module/exchangepowershell/get-adaptivescopemembers schema: 2.0.0 title: Get-AdaptiveScopeMembers From 0563ca9162883a73a477981e51968d1fdf925931 Mon Sep 17 00:00:00 2001 From: Anirudh Date: Thu, 18 Dec 2025 17:04:48 -0800 Subject: [PATCH 6/9] Update Get-AdaptiveScopeMembers.md Fix inlie reference to -adaptivereportfilters from example --- .../exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md b/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md index 37d884b1fd..f6d18df706 100644 --- a/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md +++ b/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md @@ -127,7 +127,7 @@ This example retrieves the members of the adaptive scope US Finance Sites where If the results contains fewer than 10,000 members, all are returned. For larger results, only the first 10,000 are included, and the first object in the response contains metadata with a watermark that can be used to request subsequent pages. -You can find more details about `AdaptiveReportFilters` in the [parameters section](#-AdaptiveReportFilters) +You can find more details about `AdaptiveReportFilters` in the [parameters section](#-adaptivereportfilters) ### Example 8 — Paginated results From ad69cdefaf55e4f1fb9d343f875c5888dab27447 Mon Sep 17 00:00:00 2001 From: Anirudh Date: Thu, 18 Dec 2025 17:24:50 -0800 Subject: [PATCH 7/9] Update Get-AdaptiveScopeMembers.md Change inline reference to #adaptivereportfilters --- .../exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md b/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md index f6d18df706..19d2a1b7a5 100644 --- a/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md +++ b/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md @@ -127,7 +127,7 @@ This example retrieves the members of the adaptive scope US Finance Sites where If the results contains fewer than 10,000 members, all are returned. For larger results, only the first 10,000 are included, and the first object in the response contains metadata with a watermark that can be used to request subsequent pages. -You can find more details about `AdaptiveReportFilters` in the [parameters section](#-adaptivereportfilters) +You can find more details about `AdaptiveReportFilters` in the [AdaptiveReportFilters](#adaptivereportfilters) section ### Example 8 — Paginated results From dc9379c787c219565cfd7a35a0e9cdb5a4a6f9b6 Mon Sep 17 00:00:00 2001 From: Anirudh Date: Thu, 18 Dec 2025 17:30:51 -0800 Subject: [PATCH 8/9] Update Get-AdaptiveScopeMembers.md removing in page link for now --- .../exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md b/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md index 19d2a1b7a5..16e314ede5 100644 --- a/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md +++ b/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md @@ -127,7 +127,7 @@ This example retrieves the members of the adaptive scope US Finance Sites where If the results contains fewer than 10,000 members, all are returned. For larger results, only the first 10,000 are included, and the first object in the response contains metadata with a watermark that can be used to request subsequent pages. -You can find more details about `AdaptiveReportFilters` in the [AdaptiveReportFilters](#adaptivereportfilters) section +You can find more details about `AdaptiveReportFilters` in the parameters section below ### Example 8 — Paginated results From ea05d5dab2d25d244b45ea6b26abf68be14bc821 Mon Sep 17 00:00:00 2001 From: Chris Davis Date: Fri, 19 Dec 2025 11:59:03 -0800 Subject: [PATCH 9/9] Edits Massive PowerShell schema formatting issues to correct. --- .openpublishing.redirection.exchange.json | 5 - .../Get-AdaptiveScopeMembers.md | 296 +++++++----------- 2 files changed, 116 insertions(+), 185 deletions(-) diff --git a/.openpublishing.redirection.exchange.json b/.openpublishing.redirection.exchange.json index a907bcaba7..e13a297239 100644 --- a/.openpublishing.redirection.exchange.json +++ b/.openpublishing.redirection.exchange.json @@ -7995,11 +7995,6 @@ "redirect_url": "/powershell/module/exchangepowershell/get-adaptivescope", "redirect_document_id": true }, - { - "source_path": "exchange/virtual-folder/exchange/Get-AdaptiveScopeMembers.md", - "redirect_url": "/powershell/module/exchangepowershell/get-adaptivescopemembers", - "redirect_document_id": true - }, { "source_path": "exchange/virtual-folder/exchange/Get-AddressBookPolicy.md", "redirect_url": "/powershell/module/exchangepowershell/get-addressbookpolicy", diff --git a/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md b/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md index 16e314ede5..0d9332732a 100644 --- a/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md +++ b/exchange/exchange-ps/ExchangePowerShell/Get-AdaptiveScopeMembers.md @@ -1,10 +1,11 @@ --- applicable: Exchange Online, Security & Compliance -author: amuralidhara +author: chrisda external help file: Microsoft.Exchange.TransportMailflow-Help.xml Locale: en-US Module Name: ExchangePowerShell -ms.author: amuralidhara +ms.author: chrisda +ms.reviewer: amuralidhara online version: https://learn.microsoft.com/powershell/module/exchangepowershell/get-adaptivescopemembers schema: 2.0.0 title: Get-AdaptiveScopeMembers @@ -47,91 +48,84 @@ Get-AdaptiveScopeMembers [-Identity] -PageCookie **⚠️ Warning:** -> Although you *can* specify `Unlimited` to retrieve all members in a single request, this is **not recommended** for large adaptive scopes. Using `Unlimited` may lead to long‑running requests and increases the likelihood of transient failures that cannot be efficiently retried. +**Important**: We don't recommend using the PageResultSize value Unlimited for large adaptive scopes. Using Unlimited on large adaptive scopes might lead to long‑running requests and transient failures that can't be efficiently retried. -### Example 3 - Retrieve only the count of members in the adaptive scope +### Example 3 ```powershell Get-AdaptiveScopeMembers -Identity "US Finance Users" -PageResultSize 0 ``` -This example only returns the metadata with total member count of the adaptive scope US Finance Users. +This example only returns metadata with total member count of the adaptive scope US Finance Users. - -### Example 4 - Retrieve up to 30 members of the adaptive scope +### Example 4 ```powershell Get-AdaptiveScopeMembers -Identity "US Finance Users" -PageResultSize 30 ``` -This example retrieves the members of the adaptive scope US Finance Users. -If the scope contains fewer than 30 members, all members are returned. +This example retrieves the members of the adaptive scope US Finance Users. If the scope contains fewer than 30 members, all members are returned. + For larger scopes, only the first 30 members are included, and the first object in the response contains metadata with a watermark that can be used to request subsequent pages. -### Example 5 - Retrieve only the current members of the adaptive scope +### Example 5 ```powershell Get-AdaptiveScopeMembers -Identity "US Finance Users" -State Added ``` -This example retrieves the current members of the adaptive scope US Finance Users. -If the scope contains fewer than 10,000 current members, all current members are returned. +This example retrieves the current members of the adaptive scope US Finance Users. If the scope contains fewer than 10,000 current members, all current members are returned. + For larger scopes, only the first 10,000 current members are included, and the first object in the response contains metadata with a watermark that can be used to request subsequent pages. -### Example 6 - Retrieve only the past members of the adaptive scope +### Example 6 ```powershell Get-AdaptiveScopeMembers -Identity "US Finance Users" -State Removed ``` -This example retrieves the past members of the adaptive scope US Finance Users. -If the scope contains fewer than 10,000 past members, all past members are returned. +This example retrieves the past members of the adaptive scope US Finance Users. If the scope contains fewer than 10,000 past members, all past members are returned. + For larger scopes, only the first 10,000 past members are included, and the first object in the response contains metadata with a watermark that can be used to request subsequent pages. -### Example 7 - Retrieve a subset of members using filters +### Example 7 ```powershell Get-AdaptiveScopeMembers -Identity "US Finance Sites" -AdaptivereportFilters @{"SiteUrlContainsAny" = @("/personal/", "/teams/")} ``` -This example retrieves the members of the adaptive scope US Finance Sites where the site url contains `/personal/` or `/teams/` -If the results contains fewer than 10,000 members, all are returned. -For larger results, only the first 10,000 are included, and the first object in the response contains metadata with a watermark that can be used to request subsequent pages. - -You can find more details about `AdaptiveReportFilters` in the parameters section below +This example retrieves the members of the adaptive scope US Finance Sites where the site url contains `/personal/` or `/teams/`. If the results contains fewer than 10,000 members, all are returned. +For larger results, only the first 10,000 are included, and the first object in the response contains metadata with a watermark that can be used to request subsequent pages. -### Example 8 — Paginated results - +### Example 8 ```powershell $scope="US Finance Users"; $size=200; $cookie=$null $all=@() @@ -142,12 +136,54 @@ do { if($meta.CurrentPageMemberCount -gt 0){ $all += $page[1..($page.Count-1)] } $cookie = if($meta.IsLastPage){ $null } else { $meta.Watermark } } while($cookie -ne $null) -$all | Export-Csv -NoTypeInformation -Path "D:\AdaptiveScopeMembers_$($scope -replace ' ','_').csv" +$all | Export-Csv -NoTypeInformation -Path "C:\Data\AdaptiveScopeMembers_$($scope -replace ' ','_').csv" +``` + +This example retrieves the members of the adaptive scope US Finance Users 200 members at a time and saves them to a list. The results are saved to the specified CSV file. + +### Example 9 +```powershell +function Export-AdaptiveScopeMembers { + [CmdletBinding()] param([string]$Scope,[string]$Out,[int]$Size=10000,[bool]$Resume=$true) + $scope=$Scope; $out=$Out; $size=$Size; + $meta=Join-Path $out "$scope-exportadaptivescopemembersexecutioninfo.json" + if (-not (Test-Path $out)) { New-Item -ItemType Directory -Path $out | Out-Null } + $m = if ($resume -and (Test-Path $meta)) { Get-Content $meta -Raw | ConvertFrom-Json } else {$null} + $cookie = if ($m) {$m.Watermark} else {$null}; $page = if ($m -and $m.IsLastPage -ne $true) { $m.LastPageProcessed + 1 } else {1}; $isLast=$false + do { + $res = if ($cookie) { Get-AdaptiveScopeMembers -Identity $scope -PageCookie $cookie -WarningAction SilentlyContinue} else { Get-AdaptiveScopeMembers -Identity $scope -PageResultSize $size -WarningAction SilentlyContinue } + $metaObj = $res[0]; $members = $res[1..($res.Count-1)] + if ($members.Count) { $file=Join-Path $out "$scope-part$($page).csv"; $members | Export-Csv $file -NoTypeInformation; Write-Host "Exported $($members.Count) of page $page to file '$file'" } + $cookie = $metaObj.Watermark; $isLast = $metaObj.IsLastPage + $status = @{TimestampUtc=(Get-Date).ToUniversalTime().ToString("o"); TotalResults=$metaObj.TotalMemberCount; PageSize=$metaObj.CurrentPageMemberCount; Identity=$metaObj.Identity; Watermark=$cookie; LastPageProcessed=$page; IsLastPage=$metaObj.IsLastPage} + if ($isLast) { + $status = @{TimestampUtc=(Get-Date).ToUniversalTime().ToString("o"); TotalResults=$metaObj.TotalMemberCount; Identity=$metaObj.Identity; Watermark=$cookie; LastPageProcessed=$page; IsLastPage=$metaObj.IsLastPage} + } + $status | ConvertTo-Json | Set-Content $meta + $page++ + } while (-not $isLast) + Write-Host "Completed exporting members of adaptive scope '$scope' to folder '$out'" +} ``` -This example retrieves the members of the adaptive scope US Finance Users 200 members at a time and saves them to a list. -After all members are returned, it saves the list of members as a csv file. +Customers often need to export all members of an adaptive scope into files for review, auditing, offline analysis, or to share with other teams. This **Export‑AdaptiveScopeMembers** helper script simplifies this process by automatically paging through the scope, exporting each page to a CSV file, and writing execution metadata for resume. + +This export workflow is **restartable**. If the script stops midway due to a transient failure, network issue, or timeout, you can simply run it again. It reads the existing metadata file, resumes from the last successfully processed page, and continues exporting until all pages have been retrieved. + +Paste this function into your session and call it with the desired parameters. You can call `Export-AdaptiveScopeMembers` to save the results to files. + +This example retrieves the members of the adaptive scope US Finance Users and saves every 10,000 members to a csv file under the provided folder. The folder is created if it doesn't already exist: + +`Export-AdaptiveScopeMembers -Scope "US Finance Users" -Out "D:\adaptivescopedetails"`. + +This example retrieves the members of the adaptive scope US Finance Users and saves every 200 members to a csv file under the provided folder. The folder is created if it doesn't already exist: + +`Export-AdaptiveScopeMembers -Scope "US Finance Users" -Out "D:\adaptivescopedetails" -Size 200`. +By default, the -Resume parameter is set to $true, allowing the export process to automatically continue from the last completed page if a PowerShell session is interrupted. +Specify $false to start the export from the beginning and overwrite any previously saved progress. + +`Export-AdaptiveScopeMembers -Scope "US Finance Users" -Out "D:\adaptivescopedetails" -Size 200 -Resume $false` ## PARAMETERS @@ -177,72 +213,44 @@ Accept wildcard characters: False > Applicable: Exchange Online, Security & Compliance +The AdaptiveReportFilters parameter specifies one or more filters used to refine the results. -Specifies one or more filters used to refine the results returned by `Get-AdaptiveScopeMembers`. - -This parameter accepts a **PSWS hashtable**, where each key maps to a list (array) of **up to 10 values**. -Filters whose name contains **`Not`** act as exclusion filters and are typically **intersected** with other filters when multiple keys are provided. - -#### Supported Filter Keys -**Mailbox GUID filters** - -- `MailboxGuidEqualsAny` -- `MailboxGuidNotEqualsAny` - -**SMTP address filters** - -- `SmtpAddressEqualsAny` -- `SmtpAddressNotEqualsAny` -- `SmtpAddressStartsWithAny` -- `SmtpAddressNotStartsWithAny` +This parameter accepts a hash table where each key maps to a list (array) of up to 10 values. Valid filter keys are: -**ObjectId filters** +- MailboxGuidEqualsAny +- MailboxGuidNotEqualsAny +- ObjectIdEqualsAny +- ObjectIdNotEqualsAny +- SiteIdEqualsAny +- SiteIdNotEqualsAny +- SiteUrlContainsAny +- SiteUrlEqualsAny +- SiteUrlNotContainsAny +- SiteUrlNotEqualsAny +- SiteUrlNotStartsWithAny +- SiteUrlStartsWithAny +- SmtpAddressEqualsAny +- SmtpAddressNotEqualsAny +- SmtpAddressNotStartsWithAny +- SmtpAddressStartsWithAny +- UpnEqualsAny +- UpnNotEqualsAny +- UpnNotStartsWithAny +- UpnStartsWithAny -- `ObjectIdEqualsAny` -- `ObjectIdNotEqualsAny` +Multiple key values use logical OR syntax. Multiple non-\*Not\* keys use OR syntax. Mixed \*Not\* and non-\*Not\* keys use logical AND syntax. -**SharePoint Site filters** +Example parameter value to filter by UPN prefix: -- `SiteIdEqualsAny` -- `SiteIdNotEqualsAny` -- `SiteUrlEqualsAny` -- `SiteUrlNotEqualsAny` -- `SiteUrlContainsAny` -- `SiteUrlNotContainsAny` -- `SiteUrlStartsWithAny` -- `SiteUrlNotStartsWithAny` +`@{UpnStartsWithAny = @("john", "mary")` -**User Principal Name (UPN) filters** +Example parameter value to include by SMTP address AND exclude by UPN: -- `UpnEqualsAny` -- `UpnNotEqualsAny` -- `UpnStartsWithAny` -- `UpnNotStartsWithAny` +`@{SmtpAddressEqualsAny = @("alice@contoso.com","bob@contoso.com"); UpnNotEqualsAny = @("bob.old@contoso.com")}` +Example parameter value to include by SMTP address OR include by UPN -#### Example 1 — Filter by UPN prefix -```powershell --AdaptiveReportFilters @{ - UpnStartsWithAny = @("john", "mary") -} -``` - -#### Example 2 — Include by SMTP address and exclude by UPN -```powershell --AdaptiveReportFilters @{ - SmtpAddressEqualsAny = @("alice@contoso.com","bob@contoso.com") - UpnNotEqualsAny = @("bob.old@contoso.com") -} -``` - -#### Example 3 — Include by SMTP address or include by UPN -```powershell --AdaptiveReportFilters @{ - SmtpAddressEqualsAny = @("alice@contoso.com","bob@contoso.com") - UpnEqualsAny = @("bob.old@contoso.com") -} -``` - +`@{SmtpAddressEqualsAny = @("alice@contoso.com","bob@contoso.com"); UpnEqualsAny = @("bob.old@contoso.com")}` ```yaml Type: PswsHashtable @@ -260,13 +268,11 @@ Accept wildcard characters: False > Applicable: Exchange Online, Security & Compliance -Specifies the bookmark from which the cmdlet should continue retrieving results. - -Use the **`Watermark`** value returned from a previous request to the *same* adaptive scope as the value of this parameter. The watermark acts as a continuation token, allowing the cmdlet to resume exactly where the previous page ended and fetch the next page of members. +The PageCookie specifies the bookmark where the cmdlet should continue retrieving results from. -> **⚠️ Warning:** -> Do **not** manually edit or fabricate a watermark value. Doing so may cause skipped pages, duplicate results, or invalid requests. Always use the watermark exactly as returned by the cmdlet. +Use the Watermark value returned from a previous request to the same adaptive scope as the value of this parameter. The watermark acts as a continuation token, allowing the cmdlet to resume exactly where the previous page ended and fetch the next page of members. +**Important**: Manually editing or fabricating a Watermark value might cause skipped pages, duplicate results, or invalid requests. Always use the Watermark value exactly as returned by the cmdlet. ```yaml Type: string @@ -284,14 +290,11 @@ Accept wildcard characters: False > Applicable: Exchange Online, Security & Compliance -Specifies the maximum number of members to return for the request. - -> **⚠️ Warning:** -> Although you *can* specify `Unlimited` to retrieve all members in a single request, this is **not recommended** for large adaptive scopes. Using `Unlimited` may lead to long‑running requests and increases the likelihood of transient failures that cannot be efficiently retried. - +The PageResultSize parameter specifies the maximum number of members to return for the request. -For best reliability and performance, retrieve members in **multiple smaller pages** until the last page is reached. This approach introduces natural breakpoints, reduces wait times, and allows seamless retries when transient issues occur. +For best reliability and performance, retrieve members in multiple smaller pages until the last page is reached. This approach introduces natural breakpoints, reduces wait times, and allows seamless retries when transient issues occur. +**Important**: We don't recommend using the PageResultSize value Unlimited for large adaptive scopes. Using Unlimited on large adaptive scopes might lead to long‑running requests and transient failures that can't be efficiently retried. ```yaml Type: UnlimitedInt @@ -309,13 +312,10 @@ Accept wildcard characters: False > Applicable: Exchange Online, Security & Compliance -The LocationState parameter specifies the state of the members of the adaptive scope. Valid values are: +The State parameter specifies the state of the members of the adaptive scope. Valid values are: -- Added -- Removed - -State Added specifies members which are current members of the adaptive scope. -State Removed specifies members which were once active members but have since been removed from membership. +- Added: Current members of the adaptive scope. +- Removed: Former members of the adaptive scope. ```yaml Type: LocationState @@ -332,70 +332,6 @@ Accept wildcard characters: False ### CommonParameters This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](https://go.microsoft.com/fwlink/p/?LinkID=113216). - -## Export to files - -### Description - -Customers often need to export all members of an adaptive scope into files for review, auditing, offline analysis, or to share with other teams. -The **Export‑AdaptiveScopeMembers** helper script simplifies this process by automatically paging through the scope, exporting each page to a CSV file, and writing execution metadata for resume. - -This export workflow is **restartable**. -If the script stops midway due to a transient failure, network issue, or timeout, you can simply run it again. It will read the existing metadata file, resume from the last successfully processed page, and continue exporting until all pages have been retrieved. - -### Usage - -Paste the following PowerShell function into your session and call it with the desired parameters. - - -``` -function Export-AdaptiveScopeMembers { - [CmdletBinding()] param([string]$Scope,[string]$Out,[int]$Size=10000,[bool]$Resume=$true) - $scope=$Scope; $out=$Out; $size=$Size; - $meta=Join-Path $out "$scope-exportadaptivescopemembersexecutioninfo.json" - if (-not (Test-Path $out)) { New-Item -ItemType Directory -Path $out | Out-Null } - $m = if ($resume -and (Test-Path $meta)) { Get-Content $meta -Raw | ConvertFrom-Json } else {$null} - $cookie = if ($m) {$m.Watermark} else {$null}; $page = if ($m -and $m.IsLastPage -ne $true) { $m.LastPageProcessed + 1 } else {1}; $isLast=$false - do { - $res = if ($cookie) { Get-AdaptiveScopeMembers -Identity $scope -PageCookie $cookie -WarningAction SilentlyContinue} else { Get-AdaptiveScopeMembers -Identity $scope -PageResultSize $size -WarningAction SilentlyContinue } - $metaObj = $res[0]; $members = $res[1..($res.Count-1)] - if ($members.Count) { $file=Join-Path $out "$scope-part$($page).csv"; $members | Export-Csv $file -NoTypeInformation; Write-Host "Exported $($members.Count) of page $page to file '$file'" } - $cookie = $metaObj.Watermark; $isLast = $metaObj.IsLastPage - $status = @{TimestampUtc=(Get-Date).ToUniversalTime().ToString("o"); TotalResults=$metaObj.TotalMemberCount; PageSize=$metaObj.CurrentPageMemberCount; Identity=$metaObj.Identity; Watermark=$cookie; LastPageProcessed=$page; IsLastPage=$metaObj.IsLastPage} - if ($isLast) { - $status = @{TimestampUtc=(Get-Date).ToUniversalTime().ToString("o"); TotalResults=$metaObj.TotalMemberCount; Identity=$metaObj.Identity; Watermark=$cookie; LastPageProcessed=$page; IsLastPage=$metaObj.IsLastPage} - } - $status | ConvertTo-Json | Set-Content $meta - $page++ - } while (-not $isLast) - Write-Host "Completed exporting members of adaptive scope '$scope' to folder '$out'" -} -``` - -Users can now call `Export-AdaptiveScopeMembers` to save the results to files in their disk - -### Example 1 -```powershell -Export-AdaptiveScopeMembers -Scope "US Finance Users" -Out "D:\adaptivescopedetails" -``` - -This example retrieves the members of the adaptive scope US Finance Users and saves every 10000 members to a csv file under the provided folder. The folder is created if it doesn't already exist. - -### Example 2 -```powershell -Export-AdaptiveScopeMembers -Scope "US Finance Users" -Out "D:\adaptivescopedetails" -Size 200 -``` - -This example retrieves the members of the adaptive scope US Finance Users and saves every 200 members to a csv file under the provided folder. The folder is created if it doesn't already exist. - -### Example 3 -```powershell -Export-AdaptiveScopeMembers -Scope "US Finance Users" -Out "D:\adaptivescopedetails" -Size 200 -Resume $false -``` - -By default, the -Resume parameter is set to $true, allowing the export process to automatically continue from the last completed page if a PowerShell session is interrupted. -Specify $false to start the export from the beginning and overwrite any previously saved progress. - ## INPUTS ## OUTPUTS