PowerShell Module Options
Traditional SPO Module
Microsoft.Online.SharePoint.PowerShell
- Official Microsoft module
- Tenant-level administration
- Site collection management
- User and group operations
- Compliance and security settings
Modern PnP Module
PnP.PowerShell
- Community-driven, Microsoft-supported
- Site-level and content operations
- Modern authentication features
- Cross-platform compatibility
- Extensive functionality and flexibility
Installation and Setup
Prerequisites
- PowerShell 5.1+: Windows PowerShell 5.1 or PowerShell 7+
- Execution Policy: Set to RemoteSigned or Unrestricted for module installation
- Administrative Permissions: Global Admin or SharePoint Admin roles
- Modern Authentication: Azure AD account with MFA support
Module Installation
# Step 1: Set Execution Policy (Run as Administrator)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
# Step 2: Install SharePoint Online PowerShell Module
Install-Module -Name Microsoft.Online.SharePoint.PowerShell -Force -AllowClobber
# Step 3: Install PnP PowerShell (Recommended for modern scenarios)
Install-Module -Name PnP.PowerShell -Force -AllowClobber
# Step 4: Verify Installation
Get-Module -Name Microsoft.Online.SharePoint.PowerShell -ListAvailable
Get-Module -Name PnP.PowerShell -ListAvailable
# Step 5: Update Modules (run periodically)
Update-Module -Name Microsoft.Online.SharePoint.PowerShell
Update-Module -Name PnP.PowerShell
Connection Methods
SPO Admin Center Connection
# Traditional SPO Connection (Tenant Administration)
Connect-SPOService -Url https://[tenant]-admin.sharepoint.com
# With Modern Authentication (supports MFA)
Connect-SPOService -Url https://[tenant]-admin.sharepoint.com -ModernAuth $true
# Verify Connection
Get-SPOTenant
PnP PowerShell Connection
# Modern PnP Connection (Interactive with MFA support)
Connect-PnPOnline -Url https://[tenant].sharepoint.com/sites/[sitename] -Interactive
# Connection with specific credentials
Connect-PnPOnline -Url https://[tenant].sharepoint.com/sites/[sitename] -Credentials (Get-Credential)
# Admin Center Connection with PnP
Connect-PnPOnline -Url https://[tenant]-admin.sharepoint.com -Interactive
# Verify Connection
Get-PnPWeb
Get-PnPContext
Essential Administrative Tasks
Site Collection Management
# Get Site Collection Information
Get-SPOSite -Identity https://contoso.sharepoint.com/sites/teamsite
Get-SPOSite -Limit All | Where-Object {$_.Title -like "*Finance*"}
# Create New Site Collection
New-SPOSite -Url https://contoso.sharepoint.com/sites/newproject `
-Owner admin@contoso.com `
-StorageQuota 1000 `
-Template "STS#3" `
-Title "New Project Site"
# Modify Site Properties
Set-SPOSite -Identity https://contoso.sharepoint.com/sites/teamsite `
-StorageQuota 2000 `
-SharingCapability ExternalUserSharingOnly
# Remove Site Collection (moves to recycle bin)
Remove-SPOSite -Identity https://contoso.sharepoint.com/sites/oldsite -Confirm:$false
# Permanently Delete Site
Remove-SPODeletedSite -Identity https://contoso.sharepoint.com/sites/oldsite -Confirm:$false
User and Permission Management
# Add Site Collection Administrator
Set-SPOUser -Site https://contoso.sharepoint.com/sites/teamsite `
-LoginName user@contoso.com `
-IsSiteCollectionAdmin $true
# Get Site Users and Groups
Get-SPOSiteGroup -Site https://contoso.sharepoint.com/sites/teamsite
Get-SPOUser -Site https://contoso.sharepoint.com/sites/teamsite
# Manage External User Access
Add-SPOUser -Site https://contoso.sharepoint.com/sites/teamsite `
-LoginName external@partner.com `
-Group "Team Site Visitors"
# Remove User Access
Remove-SPOUser -Site https://contoso.sharepoint.com/sites/teamsite `
-LoginName user@contoso.com
Search Configuration and Management
# Request Site Reindexing
Request-SPOReIndexWeb -Identity https://contoso.sharepoint.com/sites/teamsite
# Request List Reindexing
Request-SPOReIndexList -Identity https://contoso.sharepoint.com/sites/teamsite/lists/documents
# Export Search Configuration
Export-SPOSearchConfiguration -Owner "tenant" -Path "C:\SearchConfig.xml"
# Import Search Configuration
Import-SPOSearchConfiguration -Path "C:\SearchConfig.xml" -Owner "tenant"
# Get Search Center URL
Get-SPOTenant | Select SearchCenterUrl
Advanced PnP PowerShell Operations
List and Library Management
# Get All Lists
$lists = Get-PnPList
$documentLibraries = Get-PnPList | Where-Object {$_.BaseType -eq "DocumentLibrary"}
# Create New List
New-PnPList -Title "Project Tasks" -Template GenericList -Url "Lists/ProjectTasks"
# Create Document Library
New-PnPList -Title "Project Documents" -Template DocumentLibrary -Url "ProjectDocs"
# Add List Items
Add-PnPListItem -List "Project Tasks" -Values @{
"Title" = "Complete Analysis"
"Priority" = "High"
"DueDate" = "2025-09-30"
}
# Update List Items
Set-PnPListItem -List "Project Tasks" -Identity 1 -Values @{
"Status" = "Completed"
}
# Get List Items with Filtering
$items = Get-PnPListItem -List "Project Tasks" -Query "High"
Content Type and Field Management
# Get Content Types
$contentTypes = Get-PnPContentType
$documentCT = Get-PnPContentType -Identity "Document"
# Create New Content Type
$newCT = Add-PnPContentType -Name "Project Document" -Group "Custom Content Types" -ParentContentType $documentCT
# Add Field to Content Type
$field = Get-PnPField -Identity "ProjectPhase"
Add-PnPFieldToContentType -Field $field -ContentType $newCT
# Create Custom Field
Add-PnPField -DisplayName "Project Phase" -InternalName "ProjectPhase" -Type Choice -Choices @("Planning","Development","Testing","Deployment")
# Add Content Type to List
Add-PnPContentTypeToList -List "Project Documents" -ContentType $newCT
File and Document Management
# Upload Files
Add-PnPFile -Path "C:\Documents\ProjectPlan.docx" -Folder "Project Documents"
# Upload Large Files (>100MB)
Add-PnPFile -Path "C:\LargeFiles\Database.bak" -Folder "Backups" -UseWebDav
# Download Files
Get-PnPFile -Url "/sites/teamsite/Project Documents/ProjectPlan.docx" -Path "C:\Downloads\" -Filename "ProjectPlan.docx" -AsFile
# Copy Files Between Libraries
Copy-PnPFile -SourceUrl "/sites/source/Documents/file.docx" -TargetUrl "/sites/target/Archive/file.docx"
# Set File Properties
Set-PnPFileCheckedOut -Url "/sites/teamsite/Documents/ProjectPlan.docx"
Set-PnPFileCheckedIn -Url "/sites/teamsite/Documents/ProjectPlan.docx" -Comment "Updated project timeline"
Bulk Operations and Automation
Site Provisioning Script
# Bulk Site Creation Script
$siteRequests = @(
@{Name="Finance Team"; Url="finance"; Owner="finance-lead@contoso.com"},
@{Name="HR Team"; Url="hr"; Owner="hr-lead@contoso.com"},
@{Name="IT Team"; Url="it"; Owner="it-lead@contoso.com"}
)
Connect-SPOService -Url https://contoso-admin.sharepoint.com -ModernAuth $true
foreach ($site in $siteRequests) {
try {
New-SPOSite -Url "https://contoso.sharepoint.com/sites/$($site.Url)" `
-Owner $site.Owner `
-Title $site.Name `
-StorageQuota 1000 `
-Template "STS#3"
Write-Host "✓ Created site: $($site.Name)" -ForegroundColor Green
}
catch {
Write-Host "✗ Failed to create site: $($site.Name) - $($_.Exception.Message)" -ForegroundColor Red
}
}
User Audit and Reporting
# Site User Audit Script
$auditResults = @()
$sites = Get-SPOSite -Limit All
foreach ($site in $sites) {
try {
Connect-PnPOnline -Url $site.Url -Interactive
$users = Get-PnPUser | Where-Object {$_.Email -ne ""}
foreach ($user in $users) {
$auditResults += [PSCustomObject]@{
SiteUrl = $site.Url
SiteTitle = $site.Title
UserEmail = $user.Email
UserTitle = $user.Title
IsSiteAdmin = $user.IsSiteAdmin
LastLoginTime = $user.UsageLocation
}
}
}
catch {
Write-Warning "Could not process site: $($site.Url)"
}
}
# Export Results
$auditResults | Export-Csv -Path "C:\Reports\SharePointUserAudit.csv" -NoTypeInformation
Best Practices
Script Development and Testing
- Test in Development: Always test scripts in development environments first
- Error Handling: Implement try-catch blocks for robust error management
- Progress Tracking: Use Write-Progress for long-running operations
- Logging: Implement comprehensive logging for audit trails
- Parameterization: Use parameters and configuration files for flexibility
Authentication and Security
- Modern Authentication: Always use modern authentication with MFA support
- Service Accounts: Use dedicated service accounts for automated scripts
- Certificate Authentication: Consider certificate-based authentication for production
- Least Privilege: Use accounts with minimum required permissions
- Session Management: Properly disconnect sessions after operations
Performance Optimization
- Batch Operations: Use batch operations for multiple related tasks
- Throttling Awareness: Implement delays to avoid throttling
- Parallel Processing: Use parallel execution for independent operations
- Efficient Queries: Use CAML queries and filters to limit data retrieval
- Connection Reuse: Reuse connections within script execution
Troubleshooting Common Issues
Authentication Problems
Common Authentication Issues
- MFA Challenges: Use -Interactive parameter for MFA-enabled accounts
- Conditional Access: Ensure PowerShell access is allowed in conditional access policies
- Legacy Authentication: Verify modern authentication is enabled for the tenant
- Application Permissions: Check Azure AD app registrations and permissions
# Troubleshooting Authentication
# Test basic connectivity
Test-NetConnection login.microsoftonline.com -Port 443
# Check authentication method
Connect-PnPOnline -Url https://tenant.sharepoint.com/sites/site -Interactive -ForceAuthentication
# Verify context
$context = Get-PnPContext
Write-Host "Connected as: $($context.Web.CurrentUser.Email)"
Permission and Access Issues
# Check User Permissions
$user = Get-PnPUser -Identity "user@contoso.com"
$permissions = Get-PnPUserPermissions -User $user
Write-Host "User permissions: $($permissions -join ', ')"
# Verify Site Collection Admin
$site = Get-SPOSite -Identity https://contoso.sharepoint.com/sites/teamsite
Write-Host "Site Collection Admins: $($site.Owner)"
# Test Site Access
try {
Connect-PnPOnline -Url $siteUrl -Interactive
$web = Get-PnPWeb
Write-Host "✓ Access confirmed: $($web.Title)" -ForegroundColor Green
}
catch {
Write-Host "✗ Access denied: $($_.Exception.Message)" -ForegroundColor Red
}
Module and Version Issues
# Check Module Versions
Get-Module -Name PnP.PowerShell -ListAvailable | Select Version, ModuleBase
Get-Module -Name Microsoft.Online.SharePoint.PowerShell -ListAvailable | Select Version
# Update Modules
Update-Module -Name PnP.PowerShell -Force
Update-Module -Name Microsoft.Online.SharePoint.PowerShell -Force
# Resolve Module Conflicts
Remove-Module -Name PnP.PowerShell -Force
Import-Module -Name PnP.PowerShell -Force
# Check PowerShell Version
$PSVersionTable.PSVersion
Integration with Other SharePoint Tools
PowerShell + SharePoint Designer Replacement
- Workflow Migration: Use Power Automate with PowerShell triggers
- Custom Forms: PowerApps integration with PowerShell data sources
- Site Templates: PowerShell-based site provisioning replacing SPD templates
- Data Views: PnP PowerShell for creating custom list views and web parts
PowerShell + Microsoft 365 CLI
# Cross-platform alternative using Microsoft 365 CLI
npm install -g @pnp/cli-microsoft365
# Login
m365 login
# SharePoint operations
m365 spo site list
m365 spo site add --url https://contoso.sharepoint.com/sites/newsite --title "New Site"
m365 spo list add --webUrl https://contoso.sharepoint.com/sites/site --title "New List"
About the Author: Nagendra Jayaram is a Microsoft Sr Technical Advisor with 18+ years of enterprise experience specializing in SharePoint Online automation and PowerShell administration.