Velin Georgiev Blog

PnPPowerShell tips and tricks

It happens that I always google the same content over and over and spend time to find the same thing twice. This post is just about short SharePoint Online PnP PowerShell code snippets for quick reference.

Install PnP Powershell on the local machine

If you do not have the PnP PowerShell cmdlets on your machine you can find my guide on how to install the

PnP SharePoint Online modules here

Get more details about SharePoint list item using the Get-PnPListItem cmdlet

Sometimes we have to further investigate what data has a specific list item, but the Get-PnPListItem cmdlet does not give you more than Title and ID if executed without additional -Fields parameter. Event with the Fields parameter included is still a bit tricky to display the fields on the screen since the param would tell the CSOM to retrieve the fields, but not to display them. Here is how you can get the list item fields data and also output it on the screen.

Connect-PnPOnline -Url -Credentials cred
$item = Get-PnPListItem -List MySystemPages -UniqueId 447bc02c-4115-46ee-aaf8-266c97977966 -Fields Id,Title,LinkFilename,FileLeafRef,LinkFilenameNoMenu,GUID
$item | %{new-object PSObject -Property @{Id=$_["Id"];LinkFilename=$_["LinkFilename"];FileLeafRef=$_["FileLeafRef"];LinkFilenameNoMenu=$_["LinkFilenameNoMenu"];Title=$_["Title"];Name=$_["Name"]}} | select Id,LinkFilename,FileLeafRef,LinkFilenameNoMenu,Title,Name

Add site catalog to a SharePoint site collection

Shortcut for adding site collection app catalog.

Connect-SPOService -Credentials mysite
$site = Get-SPOSite
Add-SPOSiteCollectionAppCatalog -Site $site

Change SharePoint Content Type

Occasionally, we have to change content types to reflect the new matadata requirements. Here is how fields can be added or removed from content type.

Connect-PnPOnline -Url -Credentials cred

# Adds two new fields to be added to the
Add-PnPField -DisplayName 'Event Start Date' -InternalName VisionEventStartDate -Type DateTime -Id ba432158-0ade-49a3-accf-5e236b5d1edc -Group Vision
Add-PnPField -DisplayName 'Event End Date' -InternalName VisionEventEndDate -Type DateTime -Id 4976778d-1c51-46a1-8384-5b6e40707a59 -Group Vision

# Remove one field from the content type
Remove-PnPFieldFromContentType -ContentType "Vision Event" -Field VisionEventDate

# Add two more
Add-PnPFieldToContentType -ContentType 'Vision Event' -Field VisionEventStartDate
Add-PnPFieldToContentType -ContentType 'Vision Event' -Field VisionEventEndDate

# Validate the Content Type fields - there should be a better way to do it
$ctype = Get-PnPContentType 'Vision Event'
$ctype.Fields | where InternalName -like 'Vision*'

Add Application Customizer

App customizer can be added by adding custom action in your site so here is how that can be done with the PnP PowerShell add custom action cmdlet.

Add-PnPCustomAction -Title 'Iframe Loader for client Id fd4740ab-b1e9-4a92-b87e-818b45420368' -Location ClientSideExtension.ApplicationCustomizer -ClientSideComponentId ac9b4190-821a-4306-9869-5fd5df583057 -ClientSideComponentProperties "{ ""iframeUrl"": """ + /MySystemPages/adaljs/fd4740ab-b1e9-4a92-b87e-818b45420368-adaljs.aspx + """, ""clientId"": """ + fd4740ab-b1e9-4a92-b87e-818b45420368 + """ }"

Enable pages download

This is a non UI (hidden) site feature of a SharePoint site, but has to be enabled in order to be able to download or upload SharePoint site pages. It is disabled by default and can be enabled by below PS script.

Connect-PnPOnline -Credentials xx
$context = Get-PnPContext
$status = $null

Write-Host "Waiting... $status"
Start-Sleep -Seconds 5
$site=Get-PnPTenantSite -url -Detailed
$status = $site.Status

} while ($status -ne 'Active')

$site.DenyAddAndCustomizePages = 1 #Disabled = 1,Enabled


$site=Get-PnPTenantSite -url -Detailed

$state = $site.DenyAddAndCustomizePages
Write-Host "Done...DenyAddAndCustomizePages: $state"

Get Cert Thumbprint used by Azure AD apps

This is how a cert thumbprint can be obtained from certificate so the thumbprint can be used in Azure AD app.

$certPath = “C:\AzureADCert.cer”
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$rawCert = $cert.GetRawCertData()
$base64Cert = [System.Convert]::ToBase64String($rawCert)
$rawCertHash = $cert.GetCertHash()
$base64CertHash = [System.Convert]::ToBase64String($rawCertHash)
$KeyId = [System.Guid]::NewGuid().ToString()
$keyCredentials =
‘“keyCredentials”: [
“customKeyIdentifier”: “‘+ $base64CertHash + ‘“,
“keyId”: “‘ + $KeyId + ‘“,
“type”: “AsymmetricX509Cert”,
“usage”: “Verify”,
“value”: “‘ + $base64Cert + ‘“
Write-Host “Certificate Thumbprint:” $cert.Thumbprint

Invite group of users to group of sites

This is a common scenario where multiple users should be granted with rights on multiple sites. Here is how we can get existing SharePoint communication site group and invite users to the group.

$sites = 'mysite','mysite-en','mysite-en-1', 'mysite-en-2', 'mysite-en-3'

foreach($site in $sites){

Connect-PnPOnline -Url$site -Credentials cred

$web = Get-PnPWeb
$group = Get-PnPGroup -AssociatedOwnerGroup

$users = '',''
foreach($user in $users) {
Add-PnPUserToGroup -LoginName $user -Identity $group

Quick reference to exporting a PnP Template from site

The PnP promysiteing engine is a great way to export site template, align it and then used to create more sites from it.

Connect-PnPOnline "" -Credentials mysite

Get-PnPProvisioningTemplate -Out c:\temp\EnSite2.xml -PersistPublishingFiles

How to download modern page from SharePoint SitePages library

It is not easy to download a modern page from a modern SharePoint site pages library. Here is how you can easily do it with powershell.

Connect-PnPOnline -Url '' -Credentials pru

Get-PnPFile -AsFile -Url /sites/xxx/SitePages/Home.aspx -Filename News.aspx -Path C:\

Set modern page client side web part properties

It is not easy to download a modern page from a modern SharePoint site pages library. Here is how you can easily do it with powershell.

Connect-PnPOnline -Url '' -Credentials pru

Set-PnPFileCheckedIn -Url "/sites/$siteUrl/SitePages/News.aspx"
$myNews = Get-PnPClientSideComponent -Page News.aspx | where Title -Like MyNews
Set-PnPClientSideWebPart -Page News.aspx -Identity $myNews.InstanceId -PropertiesJson "{""description"":""MyNews"",""searchScopeContext"":""$tenantUrl/sites/xx-en"",""limitToArticles"":true, ""businessUnit"":""b67b22a5-803a-45ee-9aaf-12dd36c9ebed""}"

Set modern page client side web part single property

This is how we can update properties one by one.

Connect-PnPOnline -Url '' -Credentials pru

$myFeed = Get-PnPClientSideComponent -Page News.aspx | where Title -eq MyNews
$props = 'division','businessUnit','segment','subscriptionCode'
$props | foreach { $myFeed.Properties[$_] = $null }
$myFeed.Properties[$props[0]] = 8218ee6f-73e7-4043-8165-3f332717eeb0
Set-PnPClientSideWebPart -Page News.aspx -Identity $myFeed.InstanceId -PropertiesJson $myFeed.PropertiesJson

Deploy solution package to site collection app catalog

Thaks to the SharePoint ALM apis You can now deploy SPFx solution package to site app catalog to fully automate your pipeline. Here is how we can do it with pnp powershell:

Connect-PnPOnline -Url xx

$package = Add-PnPApp -Path ./cors-request-sender.sppkg -Scope Site
Publish-PnPApp -Identity $package.Id -SkipFeatureDeployment -Scope Site
#Remove-PnPApp -Identity 27cda787-c25c-44fd-9047-9d4e37406941 -Scope Site

Update all list items field value in one row

Poor on performance, but handy if your list has only several or dozens of items. Do not recommend it for large lists since it will take forever to update.

Get-PnPList -Identity Lists/xx| foreach {Get-PnPListItem -List $_} | foreach { Set-PnPListItem -List Lists/xx-Identity $_.ID -Values @{"SearchVisibility" = "Boomarks and search"} }

Add JavaScriptLink on Classic SharePoint site collection

Add the script, check if the script is there or remove it. Notice the site relative url when adding and different command when getting and removing.

Add-PnPJavaScriptLink -Name 'AppInsightsPerformance' -Url SiteAssets/appInsightsTracking.js -Scope Site -Sequence 100

Get-PnPCustomAction -Scope Site

Remove-PnPCustomAction -Identity cc6da0c1-b344-446d-b483-5d53a4e6d996 -Scope Site -Force

I noticed that If you upload the file to the Site Assets library, it is automatically deployed to private cdn I suppose if enabled.

There might be a time when you have to update list item values

Here is how to do it for regular fields as well as taxonomy

$items = Get-PnPListItem -List BusinessUnitRouting

foreach($item in $items) {
Write-Host $item.Id

Set-PnPListItem -List BusinessUnitRouting -Identity $item.Id -Values @{"VisionBookmarkIcon"="Globe"}
Set-PnpTaxonomyFieldValue -ListItem $item -InternalFieldName VisionSourceDivision -TermPath 'Vision|Division|Individual Solutions Group'