Find All the Stream (Classic) Web Parts During Migration to Stream in SharePoint

Another day, another opportunity to spackle the walls of SharePoint where there’s a hole. Wouldn’t it be great if you could go somewhere in the SharePoint Admin Center to see all the places you’ve used a particular Web Part in pages? Well, you can’t, so PowerShell. PnP.PowerShell, in fact.

You may be considering migrating your videos from Stream Classic to Stream in SharePoint. After all, it’s got to happen sooner or later, and the migration tool is now available for everyone. At Sympraxis, we’ve started to help our clients with these migrations, usually in the context of other work.

One thing you’re likely to want to know is where you have used the Stream (Classic) Web Part in your pages. Depending on how you do the migration, it is likely going to be a good idea to visit many of those pages to either switch to the Document Library Web Part or at least validate the Stream (Classic) Web Parts are working.

Just as I did when I upgraded from the PnP Modern Search Web Parts v3 to v4 (See: Upgrading the PnP Modern Search Web Parts from v3 to v4: Where are they?), I turned to PowerShell. I grabbed that same script and buffed it up a bit to find the Stream (Classic) Web Parts this time.

I took a bit of a different approach with this iteration, though. Rather than using search to find the pages with the Web Parts (I found it was missing some), I switched to using Get-PnPPageComponent | PnP PowerShell. This allows me to get the Web Parts (aka Page Components) in a page directly.

The script below is what I used. I’ve included some comments to indicate where you might choose to do things a bit differently, depending on your environment and your goals. I’m just outputting the info to the console, as the tenant where I’m working isn’t that dense. You may choose to output to a CSV file or something else.

Want to know more about migrating to Stream in SharePoint? Watch the recording of our AskSympraxis from November 30, 2022: Migrating from Stream Classic.

# findStreamClassicWebParts.ps1 - Inventory Stream Classic Web Parts to ensure they still work after migration

# Connect to your tenant here. This should be the only change you need to make to use this script.
$tenant = "sympmarc"
$adminConnection = Connect-PnPOnline -Url "https://$($tenant)-admin.sharepoint.com" -Interactive  -ReturnConnection

# Get all the sites to check
# Checking all the Communication Sites and Team Sites
# $sites = Get-PnPTenantSite | Where-Object { $_.Template -eq "SITEPAGEPUBLISHING#0" -or $_.Template -eq "GROUP#0" }

# Checking sites associated with the Intranet (Home Site)
$sites = Get-PnPHubSiteChild -Connection $adminConnection -Identity "https://$($tenant).sharepoint.com" | Sort-Object

# You may choose to exclude some subsets of sites
$filteredSites = $sites | Where-Object { $_ -eq "https://$($tenant).sharepoint.com/sites/Exec-BoardRelations" }

foreach ($site in $filteredSites) {
    Write-Host -BackgroundColor White -ForegroundColor Black "Looking in $($site)"

    # Get the pages
    $siteConnection = Connect-PnPOnline -Url $site -Interactive -ReturnConnection
    $pages = Get-PnPListItem -Connection $siteConnection -List "Site Pages" | Where-Object { $_.FieldValues.File_x0020_Type -eq "aspx" }

    foreach($page in $pages) {
        #Write-Host -BackgroundColor White -ForegroundColor Black "Checking $($page.FieldValues.FileLeafRef)"
        $streamPage = Get-PnPPageComponent -Connection $siteConnection -Page $page.FieldValues.FileLeafRef | Where-Object { $_.Title -eq "Stream" } | Select-Object Title, WebPartId
        if($streamPage) {
            Write-Host -BackgroundColor Green -ForegroundColor Black ">>> Found Stream Classic Web Parts in this page: $($page.FieldValues.Title) - $($page.FieldValues.FileDirRef)"
        }

    }

}

Addendum – 2023-07-20

I hot a ping from my friend Ivor Davies (@IvorDavies5) asking how to output these results to a CSV file. Here’s a version of the same script which outputs a CSV file called ModernSearchWebPartsUpgradev3tov4.csv containing the SiteUrl and PageUrl for each “hit”.

# ModernSearchWebPartsUpgradev3tov4.ps1 - Inventory PnP Modern Search Web Parts usage to upgrade from v3 to v4

# Connect to your tenant here. This should be the only change you need to make to use this script other than
# the output path for the CSV in the last line.
$tenant = "sympmarc"
Connect-PnPOnline -Url https://$($tenant)-admin.sharepoint.com -Interactive

# You can get the Ids for the v3 Web Parts by adding them to a page and running:
# Get-PnPClientSideComponent -Page "page-name" | Where-Object { Title -ne $null } | Select-Object Title, WebPartId

# Title            WebPartId
# -----            ---------
# Search Filters   e899ac12-9256-4c8d-a8ad-dbd20fc459c3
# Search Box       096b96cc-8a44-41fa-9b4d-c0ab2ab2a779
# Search Verticals 9d441773-f735-46a3-9ca0-9e2eb4bef203
# Search Results   42ad2740-3c60-49cf-971a-c44e33511b93

$webPartIds = @(
    "e899ac12-9256-4c8d-a8ad-dbd20fc459c3",
    "096b96cc-8a44-41fa-9b4d-c0ab2ab2a779",
    "9d441773-f735-46a3-9ca0-9e2eb4bef203",
    "42ad2740-3c60-49cf-971a-c44e33511b93"
    )

# Get all the sites in the tenant
$sites = Get-PnPTenantSite

# You may choose to exclude some subsets of sites
$filteredSites = $sites #| Where-Object { $_.Url -eq 'https://$($tenant).sharepoint.com/sites/DemoSite' } 

$output = @()

foreach ($site in $filteredSites) {

    # Build the query
    if($site.Url | Select-String "/sites/") {
        $query = "Path:$($site.Url) AND FileExtension:aspx AND ($($webPartIds -join " OR "))"
    } else {
        # Exclude /sites/* if looking in the root site
        $query = "Path:$($site.Url) -Path:$($site.Url)/sites/ AND FileExtension:aspx AND ($($webPartIds -join " OR "))"
    }
    #Write-Host -BackgroundColor White -ForegroundColor Black "Looking in $($site.Url)" # $($query)"

    # Submit the query
    $pages = Submit-PnPSearchQuery -Query $query -All -RelevantResults -ErrorAction SilentlyContinue | Select-Object OriginalPath 
    # If there are results, display them
    if ($pages) {
        Write-Host -BackgroundColor White -ForegroundColor Black "Found v3 Web Parts in this site: $($site.Url)" # $($query)"
        foreach ($page in $pages) {
            Write-Host -BackgroundColor Green -ForegroundColor Black ">>> Found Web Parts in this page: $($page.OriginalPath)"                
            $output += [PSCustomObject]@{
                SiteUrl = $site.Url
                PageUrl = $page.OriginalPath
            }
        }
    }

}

$output | Export-Csv -Path "./ModernSearchWebPartsUpgradev3tov4.csv" -NoTypeInformation

Similar Posts

9 Comments

  1. to not be prompted for log in over and over I suggest leaving out the ” -ReturnConnection” part in the for loop. You don’t need to specify the connection after you connect.
    This will work:
    $siteConnection = Connect-PnPOnline -Url $site -Interactive
    $streamPage = Get-PnPPageComponent -Page $page.FieldValues.FileLeafRef | Where-Object { $_.Title -eq “Stream” } | Select-Object Title, WebPartId

    1. I always use -ReturnConnection so I can be sure I’m taking an action on the correct connection. Most of my scripts end up having more than one connection, and PowerShell seems to use the last connection by default. For me, it’s a safety move that has proved very valuable.

  2. Hi Marc,

    I’ve been trying to use this, and I keep getting this error:
    Connect-PnPOnline : Invalid URI: The format of the URI could not be determined.
    At line:21 char:23
    + … onnection = Connect-PnPOnline -Url $site -Interactive -ReturnConnecti …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Connect-PnPOnline], UriFormatException
    + FullyQualifiedErrorId : System.UriFormatException,PnP.PowerShell.Commands.Base.ConnectOnline”

    I’m able to authenticate, but is there something I’m missing

  3. Hey Marc,
    Rather than searching using the title “Stream,” I suggest utilizing the WebPartId “275c0095-a77e-4f6d-a2a0-6a7626911518.” This is advised due to Microsoft’s impending release of a new Stream web part with the same title. By employing this approach, you can avoid retrieving pages containing the upcoming Stream web part and ensure more accurate results.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.