Get List with 5000 items on the Site Collections - powershell

Im trying to Get all the of the list in the Site Collections.
The script below just get the List in the specific site collection and this is working properly.
#environment variables
$username = "user.name#xxx.com"
$password = Read-Host -Prompt "Enter your password: " -AsSecureString
$url = "https://xxx.sharepoint.com/sites/xxxxxx"
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
#add SharePoint Online DLL - update the location if required
$programFiles = [environment]::getfolderpath("programfiles")
add-type -Path $programFiles'\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.dll'
# connect/authenticate to SharePoint Online and get ClientContext object..
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($url)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword)
$ctx.Credentials = $credentials
#get all the sub webs
$Web = $ctx.Web
$ctx.Load($web)
$ctx.Load($web.Webs)
$ctx.executeQuery()
Write-Host -ForegroundColor Yellow "There are:" $web.Webs.Count "sub webs in this site collection"
#get all the lists
foreach ($subweb in $web.Webs)
{
$lists = $subweb.Lists
$ctx.Load($lists)
$ctx.ExecuteQuery()
#output the list details
Foreach ($list in $lists)
{
if ($list.ItemCount -gt 5000)
{
Write-Host -ForegroundColor Yellow "The site URL is" $subweb.Url
Write-Host "List title is: " $list.Title". This list has: " $list.ItemCount " items"
}
}
}
When i try to modify it to get lists in all of the site collection. It errored out. Here is the script that i modify.
#environment variables
$username = "user.name#xxxx.com"
$password = Read-Host -Prompt "Enter your password: " -AsSecureString
$url = get-content "C:\Users\user.name\Documents\PowershellScripts\sites.txt"
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
#add SharePoint Online DLL - update the location if required
$programFiles = [environment]::getfolderpath("programfiles")
add-type -Path $programFiles'\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.dll'
# connect/authenticate to SharePoint Online and get ClientContext object..
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($url)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword)
$ctx.Credentials = $credentials
#get all the sub webs
$Web = $ctx.Web
$ctx.Load($web)
$ctx.Load($web.Webs)
$ctx.executeQuery()
foreach($urls in $url)
{
Write-Host -ForegroundColor Yellow "There are:" $web.Webs.Count "sub webs in this site collection"
#get all the lists
foreach ($subweb in $web.Webs)
{
$lists = $subweb.Lists
$ctx.Load($lists)
$ctx.ExecuteQuery()
#output the list details
Foreach ($list in $lists)
{
if ($list.ItemCount -gt 5000)
{
Write-Host -ForegroundColor Yellow "The site URL is" $subweb.Url
Write-Host "List title is: " $list.Title". This list has: " $list.ItemCount " items"
}
}
}
}
This is the error.
You cannot call a method on a null-valued expression. At
C:\Users\joshua.maniquiz\Documents\PowershellScripts\GetAllSubWebsandListswithItemCounts.ps1:22
char:1 + $ctx.executeQuery() + ~~~~~~~~~~~~~~~~~~~ + CategoryInfo :
InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId :
InvokeMethodOnNull There are: 0 sub webs in this site collection There
are: 0 sub webs in this site collection There are: 0 sub webs in this
site collection There are: 0 sub webs in this site collection There
are: 0 sub webs in this site collection
Thank you in advance for your help!

Your mixing of singular/plural with $url and $urls is at best unlucky.
If your credentials match for all sites and the $ctx object hasn't to be unloaded/released this could probaply work.
#environment variables
$username = "user.name#xxx.com"
$password = Read-Host -Prompt "Enter your password: " -AsSecureString
$sites = get-content "C:\Users\user.name\Documents\PowershellScripts\sites.txt"
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
#add SharePoint Online DLL - update the location if required
$programFiles = [environment]::getfolderpath("programfiles")
add-type -Path $programFiles'\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.dll'
ForEach($site in $sites) {
# connect/authenticate to SharePoint Online and get ClientContext object..
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($site)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword)
$ctx.Credentials = $credentials
#get all the sub webs
$Web = $ctx.Web
$ctx.Load($web)
$ctx.Load($web.Webs)
$ctx.executeQuery()
Write-Host -ForegroundColor Yellow "There are:" $web.Webs.Count "sub webs in this site collection"
#get all the lists
ForEach ($subweb in $web.Webs) {
$lists = $subweb.Lists
$ctx.Load($lists)
$ctx.ExecuteQuery()
#output the list details
ForEach ($list in $lists) {
if ($list.ItemCount -gt 5000) {
Write-Host -ForegroundColor Yellow "The site URL is" $subweb.Url
Write-Host "List title is: " $list.Title". This list has: " $list.ItemCount " items"
}
}
}
}

I rewrote your script a bit using the SharePoint PnP PowerShell cmdlets to do the same thing. I think I got implemented what you are trying to do :)
$urls = Get-Content "C:\Users\user.name\Documents\PowershellScripts\sites.txt"
$username = "user.name#xxxx.com"
$encpassword = Read-Host -Prompt "Enter your password: " -AsSecureString
$cred = New-Object -typename System.Management.Automation.PSCredential -argumentlist $username, $encpassword
foreach($url in $urls) {
Connect-PnPOnline -Url $url -Credentials $cred
$rootweb = Get-PnPWeb -Includes Webs
foreach($web in $rootweb.Webs) {
$currentWeb = Get-PnPWeb $web.Id -Includes Lists
foreach($list in $currentWeb.Lists) {
if ($list.ItemCount -gt 5000) {
Write-Host -ForegroundColor Yellow "The site URL is" $currentWeb.Url
Write-Host "List title is: " $list.Title". This list has: " $list.ItemCount " items"
}
}
}
}
Before you can run the above script you need to install the SharePoint PnP cmdlets as well, that you can do by running
Install-Module SharePointPnPPowerShellOnline
if you are running Windows 10. In other cases, see this page for more information.
With the code above I want to illustrate how you can write the same thing shorter using more high level cmdlets.
SharePoint PnP PowerShell cmdlets are cmdlets created by the SharePoint PnP community and are distributed for free to use.

Related

Error getting files. The collection has not been initialized

I am getting this error:
"Error getting files. The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested."
Code:
#Add references to SharePoint client assemblies
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("WindowsBase")
#Variables
$SiteURL = "****************"
$LibraryName = "Documents"
$FolderName = "Customer Files"
Function Get-FilesFromFolder()
{
Try
{
#Load credentials of the admin account that has access to the library
$Cred = Get-Credential
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.UserName, $Cred.Password)
#Building Context
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$Ctx.Credentials = $Credentials
#Get the library
$Library = $Ctx.Web.Lists.GetByTitle($LibraryName)
$Folders = $Library.RootFolder.Folders
$Ctx.Load($Folders)
$Ctx.ExecuteQuery()
#Get the folder by name
$Folder = $Folders | Where {$_.Name -eq $FolderName}
$Ctx.Load($Folder)
$Ctx.ExecuteQuery()
#Iterate through each file
Foreach($File in $Folder.Files)
{
#Write out each file name
Write-Host "Now printing names for files in the folder."
Write-Host "There are "$Folder.ItemCount" files in the folder."
Write-Host -f Green $File.Name
}
}
Catch
{
Write-Host -f Red "Error getting files." $_.Exception.Message
}
}
All other guides I can find show examples of code missing "$Ctx.Load($Variable)", which I have, and I am stuck.
Hoping someone can see what I am missing - Thanks.

PowerShell script for checking links in SharePoint Pages

I'm trying to check whether every page on a given Sharepoint site contains certain URL with the following PowerShell script. It seems that the foreach loop does nothing at all. Whats should be the reason for this? Also I'm not getting any error messages. I successfully changed some of the list's properties but can't process the data.
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
#Mysite URL
$site = 'https://contoso.sharepoint.com/sites/contoso'
$urlToFind = "https://google.com"
#Admin User Principal Name
$admin = 'SampleUsername'
#Get Password as secure String
$Password = "SamplePassword"
$SecurePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force
#Get the Client Context and Bind the Site Collection
$context = New-Object Microsoft.SharePoint.Client.ClientContext($site)
#Authenticate
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($admin , $SecurePassword)
$context.Credentials = $credentials
$list = $context.Web.Lists.GetByTitle('Pages')
$context.Load($list)
$query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery()
$Items = $list.GetItems($query)
$context.Load($Items)
$context.ExecuteQuery()
$dataValues = #()
$items.GetEnumerator() | % {
$dataValues += $_.FieldValues
}
$dataValues.Count #determine the amount of items
foreach($item in $dataValues)
{
write-host "inside"
write-host ""
write-host "*** PAGE *** "$item.Url
write-host ""
$file = $item.File
#get binary data, and decode into text
$data = $file.OpenBinary()
$encode = New-Object System.Text.ASCIIEncoding
$text = $encode.GetString($data)
if($text -match $urlToFind)
{
write-warning "FOUND BAD URL IN THIS DOCUMENT!"
}
else {
write-host "nothing found"
}
#comment below to parse all pages
#break
}
We are unable to foreach $list.Items to $item.
We need query $Items by
$Items = $list.GetItems([Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery())
Then
foreach($item in $Items)

Copy document library to document library sharepoint online with powershell

I am making a PowerShell script to copy content from a document library to a different document library. So far I have the following code
{
# Define final variables
$SourceUrlComplete = $SourceUrl + $SourceSite + "/" + $SourceSubSite
$DestinationUrlComplete = $SourceUrl + "Contracts"
# Set connections
Write-host "Start copy process..." -f Yellow
Write-host "1. Connect to $sourceUrlComplete" -f Yellow
$SourceConnection = Connect-PnPOnline -Url $SourceUrlComplete -ClientId $ClientId -ClientSecret $ClientSecret -WarningAction Ignore -ReturnConnection
Write-host " Connected" -f DarkGreen
Write-host "2. Connect to $TargetUrlComplete" -f Yellow
$DestinationConnection = Connect-PnPOnline -Url $DestinationUrlComplete -ClientId $ClientId -ClientSecret $ClientSecret -WarningAction Ignore -ReturnConnection
Write-host " Connected" -f DarkGreen
$SourceList = Get-PnPList -Identity $SourceLibrary -Includes RootFolder -Connection $SourceConnection
$SourceListUrl = $SourceList.RootFolder.ServerRelativeUrl
$DestinationList = Get-PnPList -Identity $DesitinationLibrary -Includes RootFolder -Connection $DestinationConnection
$DestinationListUrl = $DestinationList.RootFolder.ServerRelativeUrl
}
This works, I have connections, I have the list too. I can also use Get-PnpListItem and will get all list items. What I'm now left with is the following:
I need to look through the items and based on a custom column check a folder exists on the target
Copy the file to the target
Unfortunately, the column 'title' and 'name' are not always populated in the source item
Note: the lists are on two different sites. But if the solution is to create a temp list on-site A then copy that to site B please let me know that too.
Can someone advise on the next step? I get stuck with either coping one on one of the whole list or messages saying to use spFileCollection.add().
So what I've done now is make this function
Function ProcessFiles {
$SourceUrlComplete = $SourceUrl + $Site + "/" + $SubSite
$DestinationUrlComplete = $SourceUrl + "Contracts"
Write-host "Start copy process..." -f Yellow
Write-host " 1. Connect to $sourceUrlComplete" -f Yellow
$SourceConnection = Connect-PnPOnline -Url $SourceUrlComplete -ClientId $ClientId -ClientSecret $ClientSecret -WarningAction Ignore -ReturnConnection
Write-host " Connected" -f DarkGreen
Write-host " 2. Connect to $DestinationUrlComplete" -f Yellow
$DestinationConnection = Connect-PnPOnline -Url $DestinationUrlComplete -ClientId $ClientId -ClientSecret $ClientSecret -WarningAction Ignore -ReturnConnection
Write-host " Connected" -f DarkGreen
Write-host " 3. Process files" -f Yellow
$SourceFiles = Get-PnPFolderItem -Connection $SourceConnection -FolderSiteRelativeUrl $SourceList -ItemType File
$SourceListItems = Get-PnPListItem -List $SourceList -Connection $SourceConnection
foreach ($SourceFile in $SourceFiles) {
$process = "yes"
foreach ($SourceListItem in $SourceListItems)
{
if ($SourceListItem["FileRef"] -eq $SourceFile.ServerRelativeUrl -and $process -eq "yes")
{
$process = "no"
Write-host " - $($SourceFile.ServerRelativeUrl)" -f DarkYellow
Get-PnPFile -Url $SourceFile.ServerRelativeUrl -Path $ProcessFolder -FileName $SourceFile.Name -AsFile -Connection $SourceConnection -Force
$SourcePath = $ProcessFolder + "\" + $SourceFile.Name
$DestinationFolder = $SourceListItem["CustomerName"]
$DestinationItemValues = #{
"CustomerName" = $SourceListItem["CustomerName"]
"Title" = $SourceListItem["Title"]
"CustomerNo" = $SourceListItem["CustomerNo"]
"DocType" = $SourceListItem["DocType"]
"DocDate" = $SourceListItem["DocDate"]
"DocCode" = $SourceListItem["DocCode"]
"Modified" = $SourceListItem["Modified"]
"Created" = $SourceListItem["Created"]
"Visibility" = $SourceListItem["Visibility"]
"CompanyID" = $SourceListItem["CompanyID"]
}
$DestinationFolder = "Contracts"
if ($SourceSubSite -eq "BE")
{
$DestinationFolder = $DestinationFolder + "\SOME_FOLDER\" + $SourceListItem["CustomerName"]
Add-PnPFile -Path $SourcePath -Connection $DestinationConnection -Folder "$DestinationFolder" -Values $DestinationItemValues | Out-Null
Remove-Item $SourcePath -Recurse
Write-host " - DONE" -f DarkGreen
}
else
{
Write-host " - FAILED" -f Red
}
}
}
}
Write-host " Done" -f DarkGreen
}
Right now it works, but I download the file temporarily. I need to add something to replace special characters where the new folder is determined. I'm not sure this is the best way currently.

How to get a list of all documents from SharePoint using PowerShell?

I want to retrieve all documents from SharePoint using PowerShell, but at the moment I can only retrieve documents for a particular site.
This is the code I am using:
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
#Set Parameters
$SiteURL="https://xxx.sharepoint.com/sites/CRMDevelopment"
$LibraryName="Documents"
$ReportOutput = "C:\users\xxx\downloads\VersionHistory.csv"
Try {
#Setup Credentials to connect
$Cred= Get-Credential
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)
#Setup the context
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$Ctx.Credentials = $Credentials
#Get the web & Library
$Web=$Ctx.Web
$Ctx.Load($Web)
$List = $Web.Lists.GetByTitle($LibraryName)
$Ctx.ExecuteQuery()
#Get All Files of from the document library - Excluding Folders
$Query = New-Object Microsoft.SharePoint.Client.CamlQuery
$Query.ViewXml = "<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>0</Value></Eq></Where><OrderBy><FieldRef Name='ID' /></OrderBy></Query></View>"
$ListItems=$List.GetItems($Query)
$Ctx.Load($ListItems)
$Ctx.ExecuteQuery()
$VersionHistoryData = #()
#Iterate throgh each version of file
Foreach ($Item in $ListItems)
{
##more code goes here.
}
}
Demo to iterate all site collections by PnP PowerShell and SharePoint online management shell, if you want to access the library in all site collections, the account need access to all site collections(admin not has permissions to all site collections by default).
#region Variables
$AdminName = "admin#xxx.onmicrosoft.com"
$Password = "password"
#endregion Variables
#region Credentials
[SecureString]$SecurePass = ConvertTo-SecureString $Password -AsPlainText -Force
$credentials = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $AdminName, $(convertto-securestring $Password -asplaintext -force)
#endregion Credentials
#Config Parameters
$AdminSiteURL="https://xxx-admin.sharepoint.com"
#$ReportOutput = "C:\users\xxx\downloads\VersionHistory.csv"
#Connect to SharePoint Online Admin Center
Connect-SPOService -Url $AdminSiteURL –Credential $credentials
#Get All site collections
$SiteCollections = Get-SPOSite -Limit All
Write-Host "Total Number of Site collections Found:"$SiteCollections.count -f Yellow
#Loop through each site collection and retrieve details
Foreach ($Site in $SiteCollections)
{
#Test for specific site
#if($Site.URL -eq "https://xxx.sharepoint.com/sites/lee"){
Write-Host "Processing Site Collection :"$Site.URL -f Yellow
Connect-PnPOnline -Url $Site.URL -credentials $credentials
$items=Get-PnPListItem -List Documents -Query "<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>0</Value></Eq></Where><OrderBy><FieldRef Name='ID' /></OrderBy></Query></View>"
Foreach ($Item in $items)
{
Write-Host $Item.FieldValues["FileRef"]
}
#}
}
Write-Host "--"

SPO Powershell Set Permissions Error in RoleDefinitionBindingCollection Call

On Sharepoint Online, using Powershell, I am trying to set list item permissions, and am finding dozens of tutorials that use a RoleDefinitionBindingCollection($ctx) call...
When I do this, though, I get the following error:
New-Object : Cannot find an overload for "RoleDefinitionBindingCollection" and
the argument count: "1".At
C:\Users\thebear\Desktop\SEDA\SEDASetIPPermissions.ps1:172 char:31
+ ... entReader = New-Object Microsoft.SharePoint.Client.RoleDefinitionBind ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
I am iterating through Doclib folders, then through the Folder.Files, checking for a value in a custom field, and setting the permissions on the matching items. EDIT: Here is the full code:
# cd 'C:\Users\thebear\Desktop\SEDA'
# .\SEDASetIPPermissions test KLY KLY1
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
If($($args.Count) -ne 3)
{
Write-Host “Usage: .\SEDASetIPPermissions <'prod' or 'test'> <ProgCode i.e. 'LCL' or 'All'> <IPGroup i.e. 'KLY1' or 'All'>"
break
}
$Site = if($args[0] -eq 'prod') {'sedasearch'} elseif ($args[0] -eq 'test') {'sedasearchtest'}
$Lib = $args[1]
$IPGroup = $args[2]
# Get Connected
$Cred = Get-Credential
$Credentials = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $Cred.UserName, $Cred.Password
$Url = "https://MySite.sharepoint.com/sites/$Site"
Connect-SPOnline -Url $Url -Credentials $Credentials
# Get Client Context
$ctx = Get-SPOContext
$ctx.RequestTimeout = 1000000
$ctx.ExecuteQuery()
# Get Web & Lists
$web = $ctx.Web
$ctx.Load($web)
$ctx.Load($web.Lists)
$ctx.Load($web.RoleDefinitions)
$ctx.ExecuteQuery()
$lists = $web.Lists
# Get Site Groups
$groups = $web.SiteGroups
$ctx.Load($groups)
$ctx.ExecuteQuery()
# Get Target Group
$groupFound = $false
$ScriptStart = Get-Date
foreach ($group in $groups)
{
if ($group.Title -eq "SEDA Admins")
{
$AdminGroupID = $group.Id
}
elseif($group.Title -eq $IPGroup + " Security Group")
{
$groupFound = $true
$IPGroupID = $group.Id
Write-Host "`n'$IPGroup Security Group' Found...`n" -ForegroundColor Green
}
}
if (!$groupFound) { Write-Host "`n'$IPGroup Security Group' NOT Found...`n" -ForegroundColor Red; break }
# Get Target List
$list = $lists.GetByTitle($Lib + " Library")
$ctx.Load($list)
$ctx.Load($list.RootFolder)
$ctx.Load($list.Fields)
$ctx.ExecuteQuery()
if($list -ne $null)
{ "`n'{0}' Found...`n" -f $list.Title | Write-Host -ForegroundColor Green }
else
{ "`n'{0}' NOT Found...`n" -f $list.Title | Write-Host -ForegroundColor Red; break }
# Get List Folders
$folders = $list.RootFolder.Folders
$ctx.Load($folders)
$ctx.ExecuteQuery()
$folders = $folders | sort Name
# Set Up Group and Admin Permissions (if not already there)
$RoleDefinitions = $web.RoleDefinitions
$ctx.Load($RoleDefinitions)
$ctx.ExecuteQuery()
$foundIPGroupRole = $false
$foundIPAdminRole = $false
foreach ($role in $RoleDefinitions)
{
if ($role.Name -eq "Read")
{
$IPGroupRole = $role
$foundIPGroupRole = $true
}
elseif ($role.Name -eq "Full Control")
{
$IPAdminRole = $role
$foundIPAdminRole = $true
}
}
# Set the permissions for 'IP Group'
$roleAssignmentReader = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)
$roleAssignmentReader.Add($IPGroupRole)
# Set the permissions for 'IP Admin'
$roleAssignmentAdmin = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx)
$roleAssignmentAdmin.Add($IPAdminRole)
# Set Counters
$FileCount = 0
$FailCount = 0
foreach ($folder in $folders)
{
$FolderFileCount = 0
$ctx.Load($folder)
$ctx.Load($folder.ListItemAllFields)
$ctx.ExecuteQuery()
if ($folder.ItemCount -lt 5000)
{
$files = $folder.Files
$ctx.Load($files)
$ctx.ExecuteQuery()
"`nProcessing Folder {0}..." -f $folder.Name | Write-Host -ForegroundColor Green
}
else
{ "`nFolder {0} Exceeds 5000 Items...`n" -f $folder.Url | Write-Host -ForegroundColor Red; continue }
foreach ($file in $files)
{
$ctx.Load($file)
$ctx.Load($file.ListItemAllFields)
$ctx.ExecuteQuery()
$item = $file.ListItemAllFields
$ctx.Load($item)
$ctx.ExecuteQuery()
$name = $file.Name
$group = $item.get_item('IPGroup')
if($group -eq $IPGroup)
{
"`nProcessing File {0}...`n" -f $name | Write-Host -ForegroundColor Green;
# Break inheritance on the list item and remove existing permissons.
# NOTE: Use $item.ResetRoleInheritance() to Restore Roll Inheritance
$item.BreakRoleInheritance($false, $true)
# Apply the two permission roles to the list item.
$ctx.Load($item.RoleAssignments.Add($IPGroupID, $roleAssignmentReader))
$ctx.Load($item.RoleAssignments.Add($AdminGroupID, $roleAssignmentAdmin))
# Update the list item and execute
$item.Update()
$ctx.ExecuteQuery()
"`nProcessed File {0}...`n" -f $name | Write-Host -ForegroundColor Green;
}
$FolderFileCount += 1
if($FolderFileCount % 1000 -eq 0) { "{0}K" -f ($FolderFileCount/1000).ToString() | Write-Host }
elseif($FolderFileCount % 100 -eq 0) {Write-Host '*'}
else {Write-Host -NoNewline '.'}
}
}
“`n{0} Files Processed, {1} Error(s), Elapsed Time: {2}" -f $FileCount, $FailCount, $((Get-Date) - $ScriptStart) | Write-Host
$ctx appears to be legit... what else could be causing this error (for a day now)?
This error occurs since RoleDefinitionBindingCollection constructor expects ClientRuntimeContext object but the following line:
$ctx = Get-SPOContext
returns object of OfficeDevPnP.Core.PnPClientContext type. Even though it inherits from ClientRuntimeContext object (PnPClientContext -> ClientContext -> ClientRuntimeContext) it could not be used for instantiating of Microsoft.SharePoint.Client.RoleDefinitionBindingCollection object.
Solution
One option would be to replace the lines:
Connect-SPOnline -Url $Url -Credentials $Credentials
#Get Client Context
$ctx = Get-SPOContext
with
$ctx = Get-Context -WebUrl $Url -UserName $Credentials.UserName -Password $Credentials.Password
where
Function Get-Context([String]$WebUrl,[String]$UserName,[System.Security.SecureString]$Password) {
$context = New-Object Microsoft.SharePoint.Client.ClientContext($WebUrl)
$context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $Password)
return $context
}
which returns Microsoft.SharePoint.Client.ClientContext object.
According to this link below. The Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx) is looking for a url as an argument, not a filename.
https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.client.roledefinitionbindingcollection.aspx