SharePoint (2003 thru Online)

Tuesday, September 22, 2026

SharePoint Admin Agent

Here's a consolidated view about the SharePoint Admin Agent, the roles needed, and the impact of using PIM (Privileged Identity Management).

What can the SharePoint Admin Agent do?

The SharePoint Admin Agent can help administrators:

  • Provide guidance and best practices for SharePoint administration.
  • Search SharePoint sites based on site properties.
  • Retrieve recent actions performed in the SharePoint Admin Center.
  • Analyze organization-level and geo-level settings.
  • Review storage usage, storage trends, and storage capacity information.
  • Retrieve information about:
    • Microsoft 365 Backup protected sites (protection units)
    • Restore points
    • Restore sessions
  • Answer SharePoint and Microsoft 365 administration questions.

What it cannot do:

  • Make changes directly in your tenant.
  • Execute administrative actions on your behalf.
  • Manage permissions or perform role assignments.
  • Handle non-SharePoint administrative workloads.

What roles are needed for maximum utilization?

Minimum Required

SharePoint Advanced Management Administrator

This role is the primary role for unlocking SharePoint Admin Agent governance capabilities such as:

  • Copilot readiness assessments
  • Oversharing detection
  • Access governance analysis
  • Site lifecycle insights
  • Remediation recommendations

Strongly Recommended

SharePoint Administrator

This role allows administrators to act on the recommendations generated by the agent:

  • Manage sites
  • Configure tenant sharing settings
  • Manage site admins
  • Configure storage settings
  • Perform tenant-wide SharePoint administration

Optional

Global Administrator

Provides the broadest set of Microsoft 365 administrative permissions, including:

  • Role assignment
  • Tenant-wide administration
  • SharePoint administration

Because of its broad permissions, this role is typically reserved for a limited number of administrators.

Best Role Combination

For most organizations, the ideal combination is:

✅ SharePoint Advanced Management Administrator
✅ SharePoint Administrator

This provides both:

  • Full SharePoint Admin Agent visibility
  • Ability to execute resulting administrative actions

without requiring Global Administrator privileges.

If both roles are assigned through PIM (Privileged Identity Management)

Pros

Security and Least Privilege

  • No standing administrative access.
  • Privileges are granted only when needed.
  • Reduces attack surface and credential exposure.

Compliance and Auditability

  • Every activation is logged.
  • Clear audit trail for who activated access and why.
  • Helps satisfy compliance requirements.

Just-in-Time Administration

  • Roles are automatically removed after the activation window.
  • Reduces risk of forgotten privileged accounts.

MFA and Approval Controls

  • Can require:
    • MFA during activation
    • Business justification
    • Approval workflows

This significantly improves the security posture.

Cons

Additional Friction

  • Administrators must activate roles before using the agent fully.
  • Can slow down routine administrative work.

Possible Delays During Incidents

  • If approval workflows are required, urgent investigations may be delayed.

Session Interruptions

  • If the activation window expires while working with SharePoint Admin Agent recommendations, administrators may need to reactivate their role.

Operational Overhead

  • PIM policies require ongoing governance:
    • Approval management
    • Activation duration tuning
    • Audit review

My Recommendation

For a security-conscious Microsoft 365 environment, a common best practice is:

RoleAssignment Method
SharePoint Advanced Management AdministratorPIM Eligible
SharePoint AdministratorPIM Eligible
Global AdministratorPIM Eligible only (not permanently assigned)

This delivers the best balance between:

  • Maximum SharePoint Admin Agent functionality
  • Strong security controls
  • Reduced standing privilege risk

For someone regularly working with Microsoft Security and SharePoint governance, this model is generally considered the enterprise-grade approach.

Wednesday, March 11, 2026

PowerShell Script to update Company logos across all SharePoint Online Sites

We apply Company logos across all SharePoint Online Site Collections and subsites. When a new logo is designed, I receive requests to update them. The PowerShell script below simplifies this process.

While running this script, you will get a window prompt to login with your Global Admin/SharePoint Admin account. Enter credentials and proceed forward.

# --------------------------
# Configuration
# --------------------------
$clientId = "12a34567-f123-4567-890e-1cch23456789"
$SiteCollectionUrl = "https://yourtenant.sharepoint.com/sites/company"
$LogoUrl = "https://yourtenant.sharepoint.com/sites/BrandGuide/Images/Company_Logo.png"

# Connect to root once (to enumerate subsites)
Connect-PnPOnline -Url $SiteCollectionUrl -Interactive -ClientId $clientId

# Get root + all subsites (recursive)
$webs = Get-PnPSubWeb -Recurse -IncludeRootWeb

# ---- Count of all sites (webs) ----
$totalSites = $webs.Count
Write-Host "Total sites (root + all subsites) found: $totalSites" -ForegroundColor Cyan

# Detect if your Connect-PnPOnline supports -ReturnConnection
$hasReturnConnection = (Get-Command Connect-PnPOnline).Parameters.ContainsKey("ReturnConnection")

$success = 0
$failed  = 0

foreach ($w in $webs) {
    try {
        Write-Host "[$success/$totalSites] Updating logo for: $($w.Title) -> $($w.Url)" -ForegroundColor White

        if ($hasReturnConnection) {
            $conn = Connect-PnPOnline -Url $w.Url -Interactive -ClientId $clientId -ReturnConnection
            Set-PnPWeb -Connection $conn -SiteLogoUrl $LogoUrl   # Set-PnPWeb works on current web / via -Connection
        }
        else {
            Connect-PnPOnline -Url $w.Url -Interactive -ClientId $clientId
            Set-PnPWeb -SiteLogoUrl $LogoUrl                    #
        }

        $success++
        Write-Host "SUCCESS: $($w.Url)" -ForegroundColor Green
    }
    catch {
        $failed++
        Write-Host "FAILED: $($w.Url) | $($_.Exception.Message)" -ForegroundColor Red
    }
}

Write-Host "Logo update process complete." -ForegroundColor Cyan
Write-Host "Summary: Total=$totalSites | Success=$success | Failed=$failed" -ForegroundColor Yellow

The result shows as below.

Monday, February 23, 2026

M365 Tenant - SharePoint Online Storage Cleanup

Items in the SharePoint Online Recycle Bin, including both the first and second stages, contribute to the site's storage quota for 93 days. Storage space is only released once items are permanently deleted. 

If there is a retention policy, deleted items may be moved to the Preservation Hold Library, which also consumes storage. 

To free up space right away, delete items from the second-stage Recycle Bin, and then clean up the Preservation Hold Library.

The PowerShell script below is the most effective way to carry out these tasks across all site collections in the tenant.

#____________________________________________________________________________________________________________________________
#==================================================================================================
# OSI - Retention Exception Update + PHL Cleanup + Recycle Bin Cleanup (PnP)
# Single-Shot Mode (≤100 sites) — OPTIMIZED with PnP Batching
#==================================================================================================

#------------------------------ CONFIG -------------------------------------
$PolicyName               = "Document Retention Policy"
$ExceptionsCsvPath        = "E:\Reports\RP_Sites_2.csv"
$SitesCsvPath             = "E:\Reports\Sites_2.csv"

$IPPSSessionUPN           = "admin@spadmins.onmicrosoft.com"
$PnPClientId              = "12a34567-f123-4567-891e-2aaf34567890"

$PHLPageSize              = 2000
$BatchChunkSize           = 100        # ← items per PnP batch (100 is the sweet spot)

$EnableRecycleBinCleanup  = $true
$RecycleBinRowLimit       = 0

#------------------------------ SECTION 1: RETENTION POLICY EXCEPTIONS ---------------------------
Write-Host "=== Updating Retention Policy Exceptions (Single-Shot) ===" -ForegroundColor Cyan

[array]$excludeSites = Import-Csv -Path $ExceptionsCsvPath |
    Select-Object -ExpandProperty URL |
    ForEach-Object { $_.Trim().TrimEnd("/") } |
    Where-Object { $_ } |
    Sort-Object -Unique

Write-Host "Loaded $($excludeSites.Count) exception site URLs from $ExceptionsCsvPath"

if ($excludeSites.Count -gt 100) {
    Write-Host "ERROR: $($excludeSites.Count) sites exceed the 100-site static scoping limit." -ForegroundColor Red
    Write-Host "Use batched mode with deployment wait, or switch to Adaptive Scopes." -ForegroundColor Red
    return
}

Connect-IPPSSession -UserPrincipalName $IPPSSessionUPN

try {
    Set-RetentionCompliancePolicy `
        -Identity $PolicyName `
        -AddSharePointLocationException $excludeSites

    Write-Host "Successfully added all $($excludeSites.Count) exception sites in one call." -ForegroundColor Green
}
catch {
    Write-Host "FAILED to add exceptions: $($_.Exception.Message)" -ForegroundColor Red
}

Write-Host "Retention exception update completed." -ForegroundColor Cyan

#------------------------------ SECTION 2: PHL CLEANUP + RECYCLE BIN CLEANUP ---------------------

Write-Host "`n=== PHL Cleanup + Recycle Bin Cleanup ===" -ForegroundColor Cyan

$sites = Import-Csv -Path $SitesCsvPath
Write-Host "Loaded $($sites.Count) sites from $SitesCsvPath"

$hasClearRecycleCmd = $null -ne (Get-Command Clear-PnPRecycleBinItem -ErrorAction SilentlyContinue)

foreach ($site in $sites) {
    $siteUrl = $site.URL.Trim().TrimEnd("/")
    if (-not $siteUrl) { continue }

    Write-Host "`nProcessing site: $siteUrl" -ForegroundColor Yellow

    try {
        Connect-PnPOnline -Url $siteUrl -Interactive -ClientId $PnPClientId -ErrorAction Stop
    }
    catch {
        Write-Host "Failed to connect to $siteUrl : $($_.Exception.Message)" -ForegroundColor Red
        continue
    }

    # ── PHL Cleanup ──────────────────────────────────────────────────────
    $phl = Get-PnPList -Identity "Preservation Hold Library" -ErrorAction SilentlyContinue
    if (-not $phl) {
        Write-Host "No Preservation Hold Library found at $siteUrl" -ForegroundColor DarkGray
    }
    else {
        Write-Host "Preservation Hold Library found at $siteUrl" -ForegroundColor Green

        $items = @()
        try {
            $items = Get-PnPListItem -List "Preservation Hold Library" -PageSize $PHLPageSize -ScriptBlock {
                param($pagedItems)
                $pagedItems.Context.ExecuteQuery()
            }
        }
        catch {
            Write-Host "Failed to list PHL items at $siteUrl : $($_.Exception.Message)" -ForegroundColor Red
            $items = @()
        }

        if ($items.Count -gt 0) {
            Write-Host "$($items.Count) items found in Preservation Hold Library — deleting in batches of $BatchChunkSize..." -ForegroundColor Cyan

            # ╔══════════════════════════════════════════════════════════════╗
            # ║  OPTIMIZATION: PnP Batching — replaces item-by-item delete  ║
            # ║  Groups up to $BatchChunkSize requests into ONE API call    ║
            # ╚══════════════════════════════════════════════════════════════╝
            $totalDeleted = 0
            for ($i = 0; $i -lt $items.Count; $i += $BatchChunkSize) {

                $batch = New-PnPBatch

                $end = [Math]::Min($i + $BatchChunkSize - 1, $items.Count - 1)
                foreach ($item in $items[$i..$end]) {
                    Remove-PnPListItem -List "Preservation Hold Library" -Identity $item.Id -Batch $batch
                }

                try {
                    Invoke-PnPBatch -Batch $batch -ErrorAction Stop
                    $totalDeleted += ($end - $i + 1)
                    Write-Host "  Batch deleted items $($i+1)$($end+1) of $($items.Count)" -ForegroundColor DarkCyan
                }
                catch {
                    Write-Host "  Batch failed at items $($i+1)$($end+1): $($_.Exception.Message)" -ForegroundColor DarkYellow
                }
            }
            Write-Host "PHL cleanup complete: $totalDeleted / $($items.Count) items deleted" -ForegroundColor Green
        }
        else {
            Write-Host "No items found in Preservation Hold Library" -ForegroundColor DarkGray
        }
    }

    # ── Recycle Bin Cleanup ──────────────────────────────────────────────
    if ($EnableRecycleBinCleanup) {
        if (-not $hasClearRecycleCmd) {
            Write-Host "Clear-PnPRecycleBinItem cmdlet not found. Per PnP docs, it may require PnP.PowerShell Nightly. Skipping recycle bin cleanup." -ForegroundColor DarkYellow
        }
        else {
            try {
                if ($RecycleBinRowLimit -gt 0) {
                    Clear-PnPRecycleBinItem -All -Force -RowLimit $RecycleBinRowLimit
                }
                else {
                    Clear-PnPRecycleBinItem -All -Force
                }
                Write-Host "Recycle bins cleared for: $siteUrl" -ForegroundColor Green
            }
            catch {
                Write-Host "Failed to clear recycle bins for $siteUrl : $($_.Exception.Message)" -ForegroundColor Red
            }
        }
    }
}

Write-Host "`n=== DONE ===" -ForegroundColor Cyan

'Filter by' option for the Name column in SPO Document Library.

When I received this requirement, I reviewed several blogs and Google AI instructions, but none addressed my goal. After further research, I was able to achieve it and would like to share an article that aims to enable the 'Filter by' option for the Name column.

When a document library is first created in Modern SharePoint Online, you'll see the Name, Modified, and Modified by columns, with All Documents set as the default view.

The 'Filter by' option is available for the Modified and Modified by columns, but not for the Name column.



Top right down to '+ Create or upload' you will see Options (click on it) > Edit View.

In Edit View, under columns, after scrolling down you will notice three types of Name columns as shown below.

1. In Display, Uncheck, Name (linked to document with edit menu).
2. In Display, Check, Name (for use in forms) replace the Position from left.
3. Click OK to save the modifications.


Once redirected to the view, you will notice Filter by option for the Name column.


Thursday, March 6, 2025

Get various properties of a SharePoint site collection using different PnP Syntaxes.

 My task was to create a report detailing various properties of a SharePoint site collection. Identifying which properties corresponded to specific PowerShell syntax required additional time. 

Ultimately, I developed this script to determine which properties are available in different syntaxes such as PnPTenantSite, PnPSite, and PnPWeb in PnP.Powershell module.

This script has proven to be very useful in understanding the properties. Please adjust the input as per your requirements; I have included all site collections in the tenant. The output is exported into CSV files.

Replace your Azure App ClientID and AdminSiteUrl. When using -Interactive in Connect-PnPOnline, you will see the credentials pop-up a couple of times. I used to keep the SP admin center site logged in on the default browser with same credentials to reduce the number of interactive sessions.

# Define the parameters for the Azure AD app
$clientId = "123456-a789-b123-456c-d78901234"
$AdminSiteUrl = "https://yourtenant-admin.sharepoint.com"

# Connect to SharePoint Online using the Azure AD app credentials
Connect-PnPOnline $AdminSiteUrl -Interactive -ClientId $clientId

# Get all site collections
$siteCollections = Get-PnPTenantSite -Detailed

# Initialize arrays to store properties
$tenantSitePropertiesList = @()
$sitePropertiesList = @()
$webPropertiesList = @()

# Loop through each site collection and get detailed properties
foreach ($site in $siteCollections) {
    $siteUrl = $site.Url
   
    # Connect to each site collection
    Connect-PnPOnline -Url $siteUrl -Interactive -ClientId $clientId
   
    # Get PnPTenantSite properties
    $tenantSiteProperties = Get-PnPTenantSite -Identity $siteUrl
    $tenantSitePropertiesList += $tenantSiteProperties
   
    # Get PnPSite properties
    $siteProperties = Get-PnPSite
    $sitePropertiesList += $siteProperties
   
    # Get PnPWeb properties
    $webProperties = Get-PnPWeb
    $webPropertiesList += $webProperties
}

# Export properties to CSV files
$tenantSitePropertiesList | Export-Csv -Path "D:\PnPTenantSiteProperties.csv" -NoTypeInformation
$sitePropertiesList | Export-Csv -Path "D:\PnPSiteProperties.csv" -NoTypeInformation
$webPropertiesList | Export-Csv -Path "D:\PnPWebProperties.csv" -NoTypeInformation

# Disconnect from SharePoint Online
#Disconnect-PnPOnline

Write-Host "The detailed properties have been exported to PnPTenantSiteProperties.csv,
PnPSiteProperties.csv, and PnPWebProperties.csv."

You can also run this script on a single site collection to obtain the properties. I ran it on all site collections to cross-verify the properties.


Thursday, February 27, 2025

Sharepoint PowerShell Modules

 The Microsoft.SharePoint.Client module is part of the SharePoint Online Client Components SDK, which is used to enable development with SharePoint Online. This module allows developers to interact with SharePoint Online using client-side object model (CSOM) APIs. It provides a way to perform various operations on SharePoint Online sites, such as creating and managing lists, libraries, and site collections, as well as handling permissions and workflows[1].

The SharePoint Online Client Components SDK can be downloaded from the official Microsoft Download Center[1]. However, it is recommended to use NuGet packages rather than installing CSOM assemblies to the Global Assembly Cache (GAC)[1].

Additionally, the Microsoft.Online.SharePoint.PowerShell module is another tool that can be used to manage SharePoint Online. It allows administrators to perform tasks such as updating the SharePoint Online Management Shell and managing tenant-level settings[2].


The Microsoft.SharePoint.Client and Microsoft.Online.SharePoint.PowerShell modules serve different purposes and are used in different contexts when working with SharePoint Online.

The Microsoft.SharePoint.Client module is part of the SharePoint Online Client Components SDK. It allows developers to interact with SharePoint Online using client-side object model (CSOM) APIs. This module is primarily used for development purposes, enabling operations such as creating and managing lists, libraries, and site collections, as well as handling permissions and workflows[3].

On the other hand, the Microsoft.Online.SharePoint.PowerShell module is a set of cmdlets specifically designed for SharePoint Online administration. It allows administrators to perform various management tasks, such as updating the SharePoint Online Management Shell and managing tenant-level settings[4]. This module is used within PowerShell to automate administrative tasks and manage SharePoint Online environments more efficiently[5].

In summary, the Microsoft.SharePoint.Client module is geared towards developers for building and interacting with SharePoint Online applications, while the Microsoft.Online.SharePoint.PowerShell module is intended for administrators to manage and configure SharePoint Online environments.


Wednesday, September 25, 2024

Uninstall All Powershell Modules

The script uses the Get-InstalledModule cmdlet to identify all installed PowerShell modules. It then employs the -match operator to find modules whose names include "Microsoft". For these identified modules, the script executes the Uninstall-Module cmdlet with the -Force option to guarantee their removal. Essentially, the script is designed to remove any PowerShell module that contains "Microsoft" in its name. 

Another variable -notmatch is targeted to remove any PowerShell module that does not contain "Microsoft" in its name. 

Additionally, there's a variable, $excludedModules, which is an array holding the names of modules that you wish to keep. By using the condition -and $excludedModules -notcontains $_.Name, the script ensures it only removes "Microsoft" named modules that are not specified in the exclusion list. 

You can customize this list by substituting "ModuleName1" and "ModuleName2" with the names of the modules you'd like to exclude from being uninstalled.

# List of modules to exclude

$excludedModules = @("ModuleName1", "ModuleName2")

Get-InstalledModule | ForEach-Object {

   # Use this line uninstalls all PowerShell modules that have "Microsoft" in their name.

   if ($_.Name -match "Microsoft") {

    # Use this line uninstalls all PowerShell modules that do not have "Microsoft" in their name.

    #if ($_.Name -notmatch "Microsoft") {

        # Use this line uninstalls all PowerShell modules that have "Microsoft" in their name and exclude above List of modules.

        #if ($_.Name -match "Microsoft" -and $excludedModules -notcontains $_.Name) {

         Uninstall-Module -Name $_.Name -Force

}

 }


NOTE: In PowerShell, the # symbol is used to add comments. Comments are lines or parts of lines that are not executed as part of the script. They are used to provide explanations or notes about the code, making it easier to understand.

Thursday, August 29, 2024

Modification of Teams URL in Microsoft 365 Admin Center

Introduction

Microsoft has recently restructured how administrators can modify Teams URLs. Previously managed through the SharePoint admin center, this function has now transitioned to the Teams & Groups section within the Microsoft 365 admin center. This change aims to streamline administrative tasks and provide a more integrated user experience.

Background

The SharePoint admin center traditionally housed various features for managing team sites and associated URLs. However, as Microsoft's suite of tools has evolved, the need for a more cohesive approach to administrative functions became apparent. This led to the migration of Teams URL management to the Microsoft 365 admin center under the Teams & Groups section.

Steps to Modify Teams URL in Microsoft 365 Admin Center

To ensure a smooth transition and ease of use, follow these detailed steps to modify Teams URLs within the new location:

Accessing the Microsoft 365 Admin Center

·        Navigate to the Microsoft 365 admin center and logging in with your administrator credentials. Once logged in, you will see a navigation panel on the left-hand side of the screen.

Locating Teams & Groups

·        In the navigation panel, scroll down and select the "Teams & groups" option. Select "Active teams & groups".

Modifying the Teams URL

·        Find the specific team whose URL you wish to modify from the list of available teams. Click on the Name of the Team to open its settings and details.

·        Locate the Site address. Click the "Edit" button down to it.

·        Enter the desired new SharePoint site address and confirm the changes by clicking "Save".


Verification

·        After saving the changes, ensure that the new URL is functional by accessing the team through the updated link.

·        If any issues arise, verify the changes in the admin center and consult Microsoft support if necessary.

Conclusion

The relocation of Teams URL modification to the Teams & Groups section of the Microsoft 365 admin center represents a strategic move towards a more unified administrative environment. By following the outlined steps, administrators can efficiently manage Teams URLs and ensure seamless access for their organization.

For further assistance or detailed guidance, please refer to the official Microsoft documentation or contact support.

Thursday, June 20, 2024

Sensitivity labels Properties of all files in a Document library

Copilot is a big deal on Microsoft 365 these days. Lots of people are using it, and Sensitivity labels are getting more popular too. I had to run a PowerShell Script to get the Properties of all files in a Document library, including their Sensitivity labels. PnP PowerShell made it easy for me.

I ran the script using the PowerShell extension in Visual Studio Code.

# Connect to the SharePoint site
$siteURL = "https://gurram.sharepoint.com/sites/dev"
Connect-PnPOnline -Url $siteURL -Interactive

# The name of the document library
$libraryName = "test1"

# Retrieve all list items in the document library
$items = Get-PnPListItem -List $libraryName

# Loop through each item and retrieve FieldValuesForEdit
foreach ($item in $items) {
    # Retrieve the FieldValuesForEdit property of the list item
    $fieldValuesForEdit = Get-PnPProperty -ClientObject $item -Property "FieldValuesForEdit"
    Write-Host "Item ID:" $item.Id
    Write-Host "FieldValuesForEdit:"
    $fieldValuesForEdit.FieldValues.FileRef #FileReferenceLink
    $fieldValuesForEdit.FieldValues._IpLabelId #Label ID
    $fieldValuesForEdit.FieldValues._DisplayName #Label Display Name
}

Below screenshot shows the result.


Monday, June 10, 2024

Apply Sensitivity label to all Site collections in SharePoint admin center

With E3 license, we have to label everything manually, which is very time-consuming when we deal with many site collections.

For our project, I used a PowerShell Script to automate the process of applying Sensitivity labels to all Site Collections.

#Run the Get-Label command to retrieve the list of available labels:
Connect-IPPSSession -UserPrincipalName spadmin@gurram.onmicrosoft.com
Get-Label |ft Name, Guid, ContentType
#Copy the required label GUID
Disconnect-IPPSSession
--------------------------------------------------------------
#Connect to PnP PowerShell
Connect-PnPOnline -Url "https://gurram-admin.sharepoint.com" -Interactive

#Get All Site collections - Include Only: Team site (no M365 Group), Team site (classic experience), Project Web App site and Team sites
$Sites = Get-PnPTenantSite | Where-Object { $_.Template -eq "STS#3" -or $_.Template -eq "STS#0" -or $_.Template -eq "PWA#0" -or $_.Template -eq "GROUP#0" }

#For each site in the Site collections
ForEach ($site in $Sites) {
    #Required Label GUID from the above Script
    $LabelId = "abc123de-45f6-7g89-hi12-34j56789jk12"  
    $ctn = Connect-PnPOnline -Url $site.URL -Interactive
    $label = Get-PnPSiteSensitivityLabel -Connection $ctn

   if ($label.DisplayName -eq "") {
   #Add sensitivity Label to site
   Set-PnPTenantSite -Identity $site.URL -SensitivityLabel $LabelId
  } else {
    Write-Host $site.URL,"Not Blank"
  }
   $Object = [PSCustomObject]@{
    URL = $site.URL
    Sensitivitylabel= $label.DisplayName
    }
    $List += $Object
    #Write-Host $site.URL
    }
#Disconnect
Disconnect-PnPOnline

Apply Sensitivity Label to all Document Libraries in a Site collection

E3 ($249) and E5($449) licenses have a big price gap, and E5 license has the advantage of auto labelling. Without it, we have to label everything manually, which is very time-consuming when we deal with many site collections and a lot of content.

For our project, I used a PowerShell Script to automate the process. I applied Sensitivity labels to all Site Collections first. 

Then, using the below PowerShell Script, I applied Sensitivity labels to Document libraries in each site collection. This way, the Office files that are uploaded or updated will get the label from the Document Library. However, we still need to label other file types manually.

List all the sites in a CSV file with URL as Header (As shown below).


symbol in PowerShell script is used for comments.

# Import the CSV file
$sites = Import-Csv -Path "D:\Dev_Sites_FilesWise.csv"

# Loop through each site
foreach ($site in $sites) {
    # Connect to the SharePoint site
    Connect-PnPOnline -Url $site.Url -Interactive

# The GUID of the 'Internal Use' sensitivity label
$Label = "Internal Use"

# Retrieve all document libraries (Except Style Library) from the site
$libraries = Get-PnPList | Where-Object {
  $_.BaseTemplate -eq [Microsoft.SharePoint.Client.ListTemplateType]::DocumentLibrary
    -and $_.Title -ne "Style Library"}

# Apply the sensitivity label to each document library if it doesn't already exist and print the name
foreach ($library in $libraries) {
 # Retrieve the current sensitivity label of the document library
 $currentLabel = (Get-PnPList -Identity $library.Id).DefaultSensitivityLabelForLibrary
   
  # Check if the sensitivity label is empty
  #if ($currentLabel -eq $null) {
      if ([string]::IsNullOrWhiteSpace($currentLabel)) {
      Set-PnPList -Identity $library.Id -DefaultSensitivityLabelForLibrary $Label
      Write-Host "'Internal Use' applied to: " $library.Title
    }
  else {
      Write-Host "Sensitivity label already exists on: " $library.Title
    }
}
}
# Disconnect the session
Disconnect-PnPOnline

Thursday, May 9, 2024

Add/Remove sites (bulk list) from Search Index thru PowerShell

 We need to remove 150 sites from Search Index. We have to make sure they don't show up in search results by turning off that option for each site. The normal way of doing this is too slow for so many sites. We use a faster PowerShell script method to handle 150 sites at once.

Regular method

By default, the option Allow this site to appear in Search results is set to Yes for all Site collections in Sharepoint online. This means the site content can show up in search results.

On the site, select Settings (Wheel) icon., and then select Site settings. If you don't see Site settings, select Site information, and then select View all site settings.

Under Search, click Search and offline availability.

In the Indexing Site Content section, under Allow this site to appear in Search results, select Yes to allow the content of the site to appear in search results.


If you don't want the content to show up in search results, choose No.

NOTE: Search results are always security trimmed, so users will only see content they have permission to see.


PowerShell Script Method

List all the sites in a CSV file with URL as Header (As shown below).


# symbol in PowerShell script is used for comments.

# Connect to Admin Center
$adminSiteUrl = "https://gurram-admin.sharepoint.com/"
$adminConnection = Connect-PnPOnline -Url $AdminSiteUrl -Interactive

$CSVImport = "D:\Sites.csv"
$SitesCollections = Import-CSV -Path $CSVImport
 
ForEach($Site in $SitesCollections)
   {
         $siteCollectionConnection = Connect-PnPOnline -Url $Site.URL -Interactive
         Set-PnPSite -Identity $Site.URL -DenyAndAddCustomizePages $false
         $Web = Get-PnPWeb -Connection $siteCollectionConnection
         #Indexing Site Content = Yes(false), = No(true)
         $Web.NoCrawl = $false
         $Web.Update()
         Invoke-PnPQuery
         #To unlock the site (-LockState Unlock), To lock the site (-LockState ReadOnly)
         #we did not use the below option, because we want to delete sites later
         Set-PnPSite -Identity $Site.URL -LockState ReadOnly
         #to know the completed site
         write-host $Site.URL
    }


This script completed successfully in less than 10 minutes.