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 https://mysite.sharepoint.com/sites/mysite -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 https://mysite-admin.sharepoint.com/ -Credentials mysite
$site = Get-SPOSite https://mysite.sharepoint.com/sites/VisionTestDev1
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 https://mysite.sharepoint.com/sites/mysite-en -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.Context.Load($ctype.Fields)
$ctype.Context.ExecuteQuery()
$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 https://xx-admin.sharepoint.com -Credentials xx
$context = Get-PnPContext
$status = $null

do
{
Write-Host "Waiting... $status"
Start-Sleep -Seconds 5
$site=Get-PnPTenantSite -url https://xx.sharepoint.com/sites/velindev -Detailed
$status = $site.Status

} while ($status -ne 'Active')

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

$site.Update()
$context.ExecuteQuery()

$site=Get-PnPTenantSite -url https://xx.sharepoint.com/sites/velindev -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
$cert.Import($certPath)
$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 + ‘“
}
],’
$keyCredentials
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 https://mysite.sharepoint.com/sites/$site -Credentials cred

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

$users = 'user.name@email.onmicrosoft.com','user2.name@email.onmicrosoft.com'
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 "https://mysite.sharepoint.com/sites/portal-en-1" -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 'https://xxx.sharepoint.com/sites/xxx' -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 'https://xxx.sharepoint.com/sites/xxx' -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 'https://xxx.sharepoint.com/sites/xxx' -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 https://xx.sharepoint.com/sites/xx-Credentials 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 https://privatecdn.sharepointonline.com/prufinancial.sharepoint.com/sites/velinsearch/siteassets/appinsightstracking.js. 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'
}