51CTO Blog地址:https://blog.51cto.com/u_13969817

Microsoft决定宣布取消SharePoint Framework(SPFx)中的域隔离web部件功能。自4月2日起,2026个域隔离web部件将完全退役,并停止为现有租户工作。

如果租户仍在使用与域隔离的web部件,那么他们将看到web部件呈现和错误消息,并停止工作。从2025年4月2日起,新租户将无法使用与域隔离的web部件,这适用于所有环境。在2026年4月2日之后,将无法选择扩展域隔离web部件。

如果您的组织仍然使用与域隔离的web部件,则在推出更改后,这些部件将显示错误消息并停止工作。我们建议客户将受影响的web部件更新为常规web部件并重新部署。

若要了解您是否安装了域隔离web部件并授予了权限,您可以验证SharePoint管理中心API访问页是否包含“隔离”分组下列出的权限。

我们可以通过以下PowerShell脚本来发现域隔离web部件使用情况,提前将受影响的web部件更新为常规web部件并重新部署。

Powershell脚本如下:

<# 
.Synopsis

    Detects solutions containing domain isolated web parts and the SharePoint pages holding those web parts.
    You need to install a recent PnP PowerShell version (July 2023 or higher) to use this script.

    This script generates two CSV files in case domain isolated web parts are found:
        - solutions.csv: contains the solutions with domain isolated web parts
        - pages.csv: contains the pages holding the domain isolated web parts

    Optionally you can skip the search for pages with domain isolated web parts by using the -SkipPages parameter. 
    
    This script uses search to find the relevant pages, so when you use Connect-PnPOnline with delegated permissions you can only see 
    the pages that the current account has access to. For a complete search use Connect-PnPOnline with application permissions.

.Example

    Connect-PnPOnline https://contoso.sharepoint.com/sites/appcatalog -ClientId 0b6a3858-dbbb-489b-b63d-1905426222f8 -Tenant contoso.onmicrosoft.com -CertificatePath "c:\certificate.pfx"
    Find-DomainIsolatedWebparts.ps1 -SkipPages $false

.Notes
    
    Useful references:
        - https://aka.ms/retirement/domainisolatedwebparts/support
        - https://aka.ms/sppnp-powershell
#>

[CmdletBinding()]
param (
    [Parameter(Mandatory = $false, HelpMessage = "Skip searching for pages with domain isolated web parts.")]
    [bool]$SkipPages = $false
)
begin
{
    # Verify there's an app catalog and that we're connected to it
    $appCatalog = Get-PnPTenantAppCatalogUrl

    if ($null -eq $appCatalog) 
    {
        Write-Host "No app catalog found, exiting as there can't be any domain isolated web parts without a configured app catalog!" -ForegroundColor Green
        exit
    }

    if ($appCatalog -ne (Get-PnPConnection).Url.TrimEnd("/")) 
    {
        Write-Host "You need to connect to your tenant app catalog first. Use Connect-PnPOnline to connect to $appCatalog" -ForegroundColor Red
        exit
    }
}
process 
{ 
    # check for apps that use domain isolation
    $solutionsWithDomainIsolatedWebParts = Get-PnPListItem -List AppCatalog -Query "<View><ViewFields><FieldRef Name='Title'/><FieldRef Name='AppPublisher'/><FieldRef Name='AppShortDescription'/><FieldRef Name='AppVersion'/><FieldRef Name='IsClientSideSolutionDeployed'/><FieldRef Name='SkipFeatureDeployment'/><FieldRef Name='UniqueSolutionId'/><FieldRef Name='IsolatedDomain'/></ViewFields><Query><Where><IsNotNull><FieldRef Name='IsolatedDomain'/></IsNotNull></Where></Query></View>"

    if ($null -eq $solutionsWithDomainIsolatedWebParts) 
    {
        Write-Host "No domain isolated web parts found!" -ForegroundColor Green
        exit
    }

    $solutionsToExport = @()
    $pagesToExport = @()

    if ($SkipPages -eq $false -and [string]::IsNullOrEmpty((Get-PnPConnection).Certificate.Thumbprint)) 
    {
        Write-Host
        Write-Host "WARNING: You'll be searching for pages containing domain isolated web parts using delegated permissions. Only the pages that the current account can access will be returned. For a complete search use Connect-PnPOnline with applicaiton permissions" -ForegroundColor Yellow        
        Write-Host
    }

    # inspect the manifest to find the web part ids
    foreach ($domainIsolatedSolution in $solutionsWithDomainIsolatedWebParts) {

        if ($domainIsolatedSolution.FieldValues.IsClientSideSolutionDeployed -eq $false) 
        {
            Write-Host "Skipping solution ""$($domainIsolatedSolution.FieldValues.Title)"" as it is not deployed" -ForegroundColor Yellow
            continue
        }

        Write-Host "Solution ""$($domainIsolatedSolution.FieldValues.Title)"" contains domain isolated web parts!" -ForegroundColor Green
        Write-Host "Inspecting solution ""$($domainIsolatedSolution.FieldValues.Title)"" with id $($domainIsolatedSolution.FieldValues.UniqueSolutionId)..." -ForegroundColor Green

        $solutionsToExport += [pscustomobject]@{
            'Title' = $domainIsolatedSolution.FieldValues.Title; 
            'Solution Id' = $domainIsolatedSolution.FieldValues.UniqueSolutionId; 
            'Publisher' = $domainIsolatedSolution.FieldValues.AppPublisher;
            'Description' = $domainIsolatedSolution.FieldValues.AppShortDescription;
            'Version' = $domainIsolatedSolution.FieldValues.AppVersion;
            'Skip feature deployment' = $domainIsolatedSolution.FieldValues.SkipFeatureDeployment;
            'Isolated domain' = $domainIsolatedSolution.FieldValues.IsolatedDomain;
        }

        if ($SkipPages -eq $true) 
        {
            Write-Host "Skipping search for pages with domain isolated web parts" -ForegroundColor Yellow
            continue
        }

        $components = Get-PnPListItem -List "Lists/ComponentManifests" -Query "<View><ViewFields><FieldRef Name='ClientComponentName'/><FieldRef Name='ClientComponentId'/></ViewFields><Query><Where><Eq><FieldRef Name='SolutionId'/><Value Type='Text'>$($domainIsolatedSolution.FieldValues.UniqueSolutionId)</Value></Eq></Where></Query></View>"

        if ($null -ne $components) {
            
            foreach($component in $components) 
            {
                Write-Host "Searching for pages using component: ""$($component.FieldValues.ClientComponentName)"" with id $($component.FieldValues.ClientComponentId)..." -ForegroundColor Blue

                #Perform a search to find the pages hosting these web parts
                $pages = Submit-PnPSearchQuery -Query "FileExtension:aspx SPFxExtensionJson:$($component.FieldValues.ClientComponentId)" -All -RelevantResults | Select-Object SPWebUrl,OriginalPath

                if ($null -ne $pages) {
                    foreach($page in $pages) 
                    {
                        Write-Host $page.OriginalPath

                        $pagesToExport += [pscustomobject]@{
                            'Title' = $domainIsolatedSolution.FieldValues.Title;
                            'Publisher' = $domainIsolatedSolution.FieldValues.AppPublisher;
                            'Component' = $component.FieldValues.ClientComponentName;
                            'Component Id' = $component.FieldValues.ClientComponentId;
                            'Site' = $page.SPWebUrl; 
                            'Page' = $page.OriginalPath;
                        }
                    }
                }

                Write-Host("-" * 40) -ForegroundColor Blue
            }
        }
    }

    $solutionsToExport | Export-CSV "solutions.csv" -NoTypeInformation

    if ($SkipPages -eq $false) 
    {
        $pagesToExport | Export-CSV "pages.csv" -NoTypeInformation
    }

}