I am trying to create a new list item in a SharePoint Online list using the Pnp.PowerShell Module in a PowerShell script. Here is my code and the output:
## ... urls and security creds removed...
Connect-PnPOnline -Url $km_site -ClientId $clientid -ClientSecret $secret -WarningAction Ignore
[Microsoft.SharePoint.Client.List]$projects_list = Get-PnPList "Projects"
Write-Host $projects_list.Title -ForegroundColor Green
$lci = New-Object Microsoft.SharePoint.Client.ListItemCreationInformation -ArgumentList #()
[Microsoft.SharePoint.Client.ListItem]$new_item = $projects_list.AddItem($lci)
Write-Host $new_item.Id -ForegroundColor Cyan
$new_item["Title"] = $title
$new_item["Project_x0020_Code"] = $code
$new_item["_ExtendedDescription"] = $desc
$new_item["ContentTypeId"] = "0x010097F10B16E4516A4E80FC5C8FABF9BAC400AEEB05A0E486404FA588439EADC25541"
# Write-Host $new_item.FieldValues -ForegroundColor Cyan
$new_item.Update()
# $projects_list.Update()
Write-Host "Created!!" -ForegroundColor Yellow
Write-Host $new_item.Id -ForegroundColor Yellow
Output:
Projects
-1
Created!!
-1
The code matches what've seen in other online samples, but the list item isn't created, but it doesn't raise an error.
In my list, Title and Project Code are required and I am using a custom content type that I created in the Admin portal and then included in the 'Projects' list.
This was the solution that works.
Connect-PnPOnline -Url $km_site -ClientId $clientid -ClientSecret $secret -WarningAction Ignore
[Microsoft.SharePoint.Client.listItem]$list_item = Add-PnPListItem -List "Projects" -ContentType "Project Info" -Values #{"Title" = $title; "_ExtendedDescription"=$desc; "Project_x0020_Code"=$code}
Related
Hey Everyone so I am able to set the sharepoint sites sensitivity labels in my tenant by doing them individually using the following commands:
# Get the label (required ExchangeOnlineManagement module)
Connect-IPPSSession -userprincipalname wise#redacted
$c = Get-Credential wise#redacted
Connect-SPOService -Url https://redacted-admin.sharepoint.com -Credential $c -ModernAuth:$true -AuthenticationUrl https://login.microsoftonline.com/organizations
Set-SPOSite -identity {site_url} -SensitivityLabel:'{GUID of sens label here}'
And now I am trying to set a default label for all sites that have not been manually set by users with the following code, but its throwing the "Site already has a sensitivity label" message, meaning the if statement isnt triggering when ran from a site in a variable???
# Get the label (required ExchangeOnlineManagement module)
Connect-IPPSSession -userprincipalname wise#redacted
$c = Get-Credential wise#redacted
Connect-SPOService -Url https://redacted-admin.sharepoint.com -Credential $c -ModernAuth:$true -AuthenticationUrl https://login.microsoftonline.com/organizations
#Create a progress counter and fail counter
$count = 0
$fail = 0
#get all sites
write-host "Collecting site data" -ForegroundColor Yellow
$SiteCollections = Get-SPOSite -Limit All
write-host "Collecting site data - COMPLETED" -ForegroundColor Green
#get a count of total sites
$total = $SiteCollections.count
write-host "There are $total total sites." -ForegroundColor Green
foreach ($site in $SiteCollections){
$count++
try{
if ( $site.SensitivityLabel -eq '' ){
Set-SPOSite $site -SensitivityLabel:'{GUID}'
} else {
$label = $site.SensitivityLabel
Write-host "Site already has a sensitivity label: $label"
$site.Url | Out-File '.\Sites_already_labeled.txt' -Append
}
} catch {
$sitename = $site.Name
"Bad site: $sitename" | Out-File '.\Failed_change_sites.txt' -Append
$fail++
Write-Host "Failed site count = $fail" -ForegroundColor Blue
Write-Host "Failed site = $sitename" -ForegroundColor Blue
}
Write-Host "Processing Site $count of $total" -ForegroundColor Red
}
I have tested the if sens label = '' on singular sites and it does infact fufill the if statement so im completely lost.
Thanks ChatGPT!
It's likely that the issue is with the following line of code: if ( $site.SensitivityLabel -eq '' ). The SensitivityLabel property of a SharePoint Online site may not be an empty string when it has no label applied to it. Instead, it may be $null, so the if statement should be updated to if ( $site.SensitivityLabel -eq $null ).
I'm trying to connect to SharePoint Online but I'm getting this error and not 100% sure why so I would be really appreciated if I can get any help or suggestion why it might be.
I believe it might have to do with my tenant using MFA so just wondering how can I connect/login using MFA?.
#Variables
$SiteURL = "https://companyName-my.sharepoint.com/personal/yzqpsn_nam_corp_m_com"
$ServerRelativeUrl= "documents/Testing"
Try {
#Get Credentials to connect
$Cred= Get-Credential
#Setup the context
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$Ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)
#Get the web from URL
$Web = $Ctx.web
$Ctx.Load($Web)
$Ctx.executeQuery()
#Get the Folder object by Server Relative URL
$Folder = $Web.GetFolderByServerRelativeUrl($ServerRelativeUrl)
$Ctx.Load($Folder)
$Ctx.ExecuteQuery()
#Call the function to empty Folder
Empty-SPOFolder $Folder
#Delete the given Folder itself
Write-host -f Green "Deleting Folder:"$Folder.ServerRelativeUrl
$Folder.Recycle() | Out-Null
$Ctx.ExecuteQuery()
}
Catch {
write-host -f Red "Error:" $_.Exception.Message
}
I have been trying to take a manual step out of a process where I clone a wiki page in sharepoint (done via powershell) and then manually go to the aspx in sharepoint designer and update the textpart's default value:
EX:
<WpNs0:SPSlicerTextWebPart runat="server" MaximumCharacters="255" DefaultValue="REPLACETHISVALUE" RequireSelection="False" FilterMainControlWidthPixels="0" FilterName="Text Filter" Title="Text Filter" FrameType="BorderOnly" SuppressWebPartChrome="False" Description="Filters the contents of Web Parts by allowing users to enter a text value." ...
I'm using the following function for building the context for my copy, and I'm wondering if there is a way to pass the final ASPX site URL and manipulate the content:
function Get-SharepointContext
{
Param(
[Parameter(Mandatory=$true)]
$siteUrl,
[Parameter(Mandatory=$false)]
$cred)
If(!$cred){$cred = get-credential -UserName "$ENV:Username#$env:USERDNSDOMAIN" -Message "Login"}
[string]$username = $cred.UserName
$securePassword = $cred.Password
[Void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
$ctx.RequestTimeOut = 1000 * 60 * 10;
$ctx.AuthenticationMode =[Microsoft.SharePoint.Client.ClientAuthenticationMode]::Default
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword)
$ctx.Credentials = $credentials
$ctx.Load($ctx.Web)
$ctx.Load($ctx.Site)
$ctx.ExecuteQuery()
Return $ctx
}
Has anyone attempted this before or know of how I can actually do this?
We can change the web part properties using PnP PowerShell or CSOM code.
PnP:
#Get Current Context Site (Root)
$siteurl = "https://abc.sharepoint.com"
Connect-SPOnline -Url $siteurl
$ctx = Get-SPOContext
#Get Web Part ID
webpart = Get-SPOWebPart -ServerRelativePageUrl "/Pages/PnPPage.aspx" -Identity "Text Filter"
$webpartId = $webpart.Id
# Update WebPart
Set-SPOWebPartProperty -ServerRelativePageUrl "/Pages/PnPPage.aspx" -Identity $webpartId -Key Height -Value 500
CSOM:
function Change-WebPart {
#variables that needs to be set before starting the script
$siteURL = "https://spfire.sharepoint.com"
$userName = "mpadmin#spfire.onmicrosoft.com"
$webURL = "https://spfire.sharepoint.com"
$relativePageUrl = "/SitePages/Home.aspx"
# Let the user fill in their password in the PowerShell window
$password = Read-Host "Please enter the password for $($userName)" -AsSecureString
# set SharePoint Online credentials
$SPOCredentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($userName, $password)
# Creating client context object
$context = New-Object Microsoft.SharePoint.Client.ClientContext($webURL)
$context.credentials = $SPOCredentials
#get Page file
$page = $context.web.getFileByServerRelativeUrl($relativePageUrl)
$context.load($page)
#send the request containing all operations to the server
try{
$context.executeQuery()
}
catch{
write-host "Error: $($_.Exception.Message)" -foregroundcolor red
}
#use the WebPartManger to load the webparts on a certain page
$webPartManager = $page.GetLimitedWebPartManager([System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)
$context.load($webPartManager.webparts)
#send the request containing all operations to the server
try{
$context.executeQuery()
}
catch{
write-host "Error: $($_.Exception.Message)" -foregroundcolor red
}
#loop through all WebParts to get the correct one and change its property
foreach($webPartDefinition in $webpartmanager.webparts){
$context.Load($webPartDefinition.WebPart.Properties)
#send the request containing all operations to the server
try{
$context.executeQuery()
}
catch{
write-host "Error: $($_.Exception.Message)" -foregroundcolor red
}
#Only change the webpart with a certain title
if ($webPartDefinition.WebPart.Properties.FieldValues.Title -eq "Documents")
{
$webPartDefinition.webpart.properties["Title"] = "My Documents"
$webPartDefinition.SaveWebPartChanges()
}
}
}
Change-WebPart
Reference:
Update/Delete WebParts On SharePoint Pages Using PnP PowerShell
Editing Web Part properties with PowerShell CSOM in SharePoint
I been trying to add an import-csv into a script from technet to create sub sites on SharePoint Online. End result would be having sub sites made from a CSV. E.G. Year 7, Year 8. Year 9.
I have done the following:
Import-Csv 'C:\sp\import.csv'|`
ForEach-Object{
$Urlsub = $_.Urlsub
$Title = $_.Title
}
$wci.Url = $Urlsub
$wci.Title = $Title
The CSV:
Urlsub Title
------ -----
Year7 Year 7
Year8 Year 8
This works fine for only the last row in the CSV. It seems to overwrite everything leaving me with the last row.
If I change it to:
$Urlsub += $_.Urlsub
It will add all the columns for $Urlsub to the same array.
How can I go about importing the CSV without it overwriting the previous value ?
Full script without csv:
#Credentials to connect to office 365 site collection url
$url ="xxx"
$username="xxx"
$password="xxx"
$Password = $password |ConvertTo-SecureString -AsPlainText -force
Write-Host "Load CSOM libraries" -foregroundcolor black -backgroundcolor yellow
Set-Location $PSScriptRoot
Add-Type -Path (Resolve-Path "Microsoft.SharePoint.Client.dll")
Add-Type -Path (Resolve-Path "Microsoft.SharePoint.Client.Runtime.dll")
Write-Host " CSOM libraries" -foregroundcolor black -backgroundcolor yellow
Set-Location $PSScriptRoot
Add-Type -Path (Resolve-Path "Microsoft.SharePoint.Client.dll")
Add-Type -Path (Resolve-Path "Microsoft.SharePoint.Client.Runtime.dll")
Write-Host "CSOM libraries loaded successfully" -foregroundcolor black -backgroundcolor Green
Write-Host "authenticate to SharePoint Online Tenant site $url and get ClientContext object" -foregroundcolor black -backgroundcolor yellow
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($url)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)
$Context.Credentials = $credentials
$context.RequestTimeOut = 5000 * 60 * 10;
$web = $context.Web
$site = $context.Site
$context.Load($web)
$context.Load($site)
try
{
$context.ExecuteQuery()
Write-Host "authenticateed to SharePoint Online site collection $url and get ClientContext object succeefully" -foregroundcolor black -backgroundcolor Green
}
catch
{
Write-Host "Not able to authenticateed to SharePoint Online site collection $url $_.Exception.Message" -foregroundcolor black -backgroundcolor Red
return
}
#creating site using WebCreationInformation calss
Write-Host "creating subsite using custom webtemplate" -foregroundcolor black -backgroundcolor yellow
$wci = New-Object Microsoft.SharePoint.Client.WebCreationInformation
$wci.Url = "Year7"
$wci.Title = "Year 7"
$wci.UseSamePermissionsAsParentSite = $true
$wci.WebTemplate = "{D0714A63-356A-4B73-815B-6E1DF824237F}#Template"
$wci.Language = 1033
$blogWeb = $site.RootWeb.Webs.Add($wci);
try
{
$context.ExecuteQuery();
Write-Host "Sub site created successfully using custom webtemplate" -foregroundcolor black -backgroundcolor Green
}
catch
{
Write-Host "Error while creating the Sub site using custom webtemplate" $_.Exception.Message -foregroundcolor black -backgroundcolor RED
}
You end up with the last value because your variable assignment falls outside of the loop which is reading the CSV file. As such, you get the last thing the variable was set to (the last line from the CSV).
I expect you'll need to create instances of WebCreationInformation for each row in the csv file, then add each of those to $site.RootWeb.Webs as I attempt to do in this example.
Import-Csv 'C:\sp\import.csv' | ForEach-Object{
$wci = New-Object Microsoft.SharePoint.Client.WebCreationInformation
$wci.Url = $_.Urlsub
$wci.Title = $_.Title
$wci.UseSamePermissionsAsParentSite = $true
$wci.WebTemplate = "{D0714A63-356A-4B73-815B-6E1DF824237F}#Template"
$wci.Language = 1033
$blogWeb = $site.RootWeb.Webs.Add($wci);
}
I am trying to delete all Version History files in SharePoint Online through PowerShell. My research has provided plenty of examples on how to do this in SharePoint 2010 and 2013 but not SharePoint Online. The files reside in Document Libraries. The script below seemed promising for my task but I have been unable to modify it to work for SharePoint Online. What changes would be necessary to make it work for SharePoint Online?
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
# get site
$site = new-object Microsoft.SharePoint.SPSite("http://xxx.sharepoint.com")
# loop through webs
foreach ($web in $site.AllWebs)
{
write-host $web.url
# loop through all lists in web
foreach ($list in $web.Lists)
{
# examine if BaseType of list is NOT a Document Library
if (($list.BaseType -eq "DocumentLibrary") -and ($list.EnableVersioning))
{
# Delete all version history
foreach ($item in $list.Items)
{
# work with the file object as we're in a document library
$file = $item.File
# delete all versions
$file.Versions.DeleteAll()
}
}
}
}
$web.Dispose();
$site.Dispose();
The code below combines PowerShell and CSOM. It worked for me. You can delete all Versions or adjust the Versions to be deleted using the Counter in the Loop.
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")
$password = Read-Host -Prompt "Enter password" -AsSecureString
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials("userID#yourtenant.com", $password)
$siteUrl = "https://yourtenant.sharepoint.com/sites/yoursitecollection"
$context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
$context.Credentials = $credentials
$fileUrl = "/sites/yoursitecollection/path_to_file/filename";
$versions = $context.Web.GetFileByServerRelativeUrl($fileUrl).Versions;
$context.Load($versions)
$context.ExecuteQuery()
for($i=2;$i -lt $versions.Count-2; $i++)
{
$versions[$i].DeleteObject()
$context.ExecuteQuery()
}
For older versions of SharePoint you may need to mimic the browser. Essentially, you would request the version history page content, get the REQUESTDIGEST and VIEWSTATE, and perform POST requests to specially crafted URL and request body for each unneeded version using the obtained values.
E.g.:
$httpResponse = Invoke-WebRequest -Uri "$baseUri/_layouts/15/Versions.aspx?list=$listId&ID=$id" -UseDefaultCredentials
$httpResponse.Forms["aspnetForm"].Fields["__VIEWSTATE"]
$httpResponse.Forms["aspnetForm"].Fields["__REQUESTDIGEST"].Replace(" ","+")
...
$httpResponse = Invoke-WebRequest -UseDefaultCredentials -MaximumRedirection 0 -ErrorAction SilentlyContinue -Method "POST" `
-Uri "$baseUri/_layouts/15/versions.aspx?list=$listId&ID=$($_.ID)&col=Number&order=d&op=Delete&ver=$($_.Version)" `
-ContentType "application/x-www-form-urlencoded" -Body ("MSOWebPartPage_PostbackSource=&MSOTlPn_SelectedWpId=&MSOTlPn_View=0&MSOTlPn_ShowSettings=False&MSOGallery_SelectedLibrary=&MSOGallery_FilterString="+
"&MSOTlPn_Button=none&__EVENTTARGET=&__EVENTARGUMENT=&MSOSPWebPartManager_DisplayModeName=Browse&MSOSPWebPartManager_ExitingDesignMode=false&MSOWebPartPage_Shared=&MSOLayout_LayoutChanges=&MSOLayout_InDesignMode=&MSOSPWebPartManager_OldDisplayModeName=Browse&MSOSPWebPartManager_StartWebPartEditingName=false&MSOSPWebPartManager_EndWebPartEditing=false&_maintainWorkspaceScrollPosition=0"+
"&__REQUESTDIGEST=$digest&__VIEWSTATE=$([System.Net.WebUtility]::UrlEncode($viewstate))&__VIEWSTATEGENERATOR=01175E75&__SCROLLPOSITIONX=0&__SCROLLPOSITIONY=0"+
"&__EVENTVALIDATION=$([System.Net.WebUtility]::UrlEncode($ev))")
if ($httpResponse.StatusCode -eq 302) { #success
write-host "v" -NoNewline -foregroundcolor DarkGreen
$vCount++
} else { #some error
write-host "x" -NoNewline -foregroundcolor Red
if ($httpResponse.Forms[0].Action.StartsWith("error")) {
write-host $httpResponse.Content.Substring($httpResponse.Content.IndexOf("ctl00_PlaceHolderMain_LabelMessage")+36,300).Split("<")[0] -ForegroundColor Magenta
}
...
}
Note that it is unnecessary to follow the 302 redirect after the POST.