Getting Error while running Powershell Script to add Site Content Link - powershell

$adminUPN="xxxxx#Home500.onmicrosoft.com"
$orgName="xxxxxx"
$userCredential = Get-Credential -UserName $adminUPN -Message "Type the password."
Connect-SPOService -Url https://$orgName-admin.sharepoint.com -Credential $userCredential
# Begin the process
$loadInfo1 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
$loadInfo2 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")
$loadInfo3 = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.UserProfiles")
#Add SharePoint PowerShell SnapIn if not already added
$snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
if ($snapin -eq $null)
{
Write-Host "Loading SharePoint Powershell Snapin"
Add-PSSnapin "Microsoft.SharePoint.Powershell" -EA SilentlyContinue
}
CLS
$StartTime = $(get-date -f F)
$timeStamp = Get-Date -format "MM_dd_yy_hh_mm"
#Get Current folder file path
$invocation = (Get-Variable MyInvocation).Value
$currentPath = Split-Path $invocation.MyCommand.Path
$currentPath = $currentPath + "\"
#Config File Path
#$configPath = $currentPath + "Config.xml"
$configPath = "C:\Users\EMXBG\Downloads\Script_AddSiteContent\Script_AddSiteContent\Config.xml"
#fetching details from config.xml
[xml]$configXML = Get-Content $configPath
$inputFileName = [string]$configXML.Config.Constants.InputFileName
$errorFileName = [string]$configXML.Config.Constants.ErrorFileName
$outFilePath = [string]$configXML.Config.Constants.OutputFileName
#Source File path containing list of WebApplications in a farm.
$webApplFilePath = $currentPath + $inputFileName
#Output File path of the exported AD Security Groups with Site collection and Group Name details.
$sitesFilePath = $currentPath + $outFilePath
#File path of the file which will capture all the errors while running the script.
$errorPath = $currentPath + $errorFileName + $timeStamp + ".csv"
# Creating object to write logging into the error and output file
$sitesFile = New-Object System.IO.StreamWriter $sitesFilePath
$errorfile = New-Object System.IO.StreamWriter $errorPath
# Fetching SharePoint WebApplications list from a CSV file
$CSVData = Import-CSV -path $webApplFilePath
$sitesFile.WriteLine("SiteCollectionName"+","+"SiteURL")
$errorfile.WriteLine("SiteURL"+"`t"+"ExceptionLevel"+"`t"+"ExceptionMsg");
addSiteContentLink $CSVData
$sitesFile.Close()
$errorfile.Close()
# Function to add Site Content link in thes where it does not exists
function addSiteContentLink($CSVData)
{
try
{
$compareText = "Site contents"
foreach ($row in $CSVData)
{
$webUrl = $row.webUrl
#$username = $row.username
#$password = $row.password
#Get Web Application and credentials
#$securePass = ConvertTo-SecureString $password -AsPlainText -Force
#$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($webUrl)
#$ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePass)
# Get the collection of navigation nodes from the quick launch bar
#$web = $ctx.Web
$quickLaunch = $webUrl.Navigation.QuickLaunch
try
{
#Iterate through each iten in Quick launch menu
foreach($quickLaunch in $web)
{
if ($quickLaunch -contains $compareText)
{
Write-Host "Site Content link Exists!"
}
else
{
# Add a new navigation node
$navNode = New-Object Microsoft.SharePoint.Client.NavigationNodeCreationInformation
$navNode.AsLastNode = $true
$navNode.Title = "Site Contents"
$navNode.Url = $web.Url + "_layouts/15/viewlsts.aspx"
$navNode.IsExternal = $false
$ctx.Load($quickLaunchColl.Add($navNode))
$ctx.ExecuteQuery()
}
}
}
catch
{
Write-Host("Exception at Site Collection Url :" + $currentSite.Url)
$errorfile.WriteLine($currentSite.Url+"`t"+"`t"+$_.Exception.Message)
}
}
#Export Data to CSV
$sitesCollection | export-csv $sitesFile -notypeinformation
$site.Dispose()
}
catch
{
Write-Host("Exception at Site Collection Url :" +$currentSite.Url)
$errorfile.WriteLine($currentSite.Url+"`t"+"SiteCollection"+"`t"+$_.Exception.Message)
}
}
Below is the Error I am getting
Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null.
At C:\Users\EMXBG\Downloads\Script_AddSiteContent\Script_AddSiteContent\ScriptForSiteContentLinkQuickLaunch - Copy.ps1:126 char:29
+ $sitesCollection | export-csv $sitesFile -notypeinformation
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Export-Csv], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportCsvCommand

This error is probably because $sitesCollection is empty/null. I can't see anything in your code that assigns it a value.

Related

How to delete files from Sharepoint with exclusions list using Powershell

I’m trying to delete certain files from a Sharepoint folder, however no matter what I try, I cannot get it to delete. I have an exclusions list, for the names of pictures that should not be deleted. I have attached one of many tries. Anyone know what to do?
The exclusionslist and the loop can write out the names to delete without any problems, and the below code gives no error-codes.
$siteurl = “https://sharepoint.com/sites/Some/Sharepoint/Folder”
$username = “AdminAccount”
$securePassword = ConvertTo-SecureString “MuchSecurePassWord” -AsPlainText -Force
$O365Credential = New-Object System.Management.Automation.PsCredential($username, $securePassword)
$count = 0
$exclusions = import-csv “Downloads\exclusions.txt”
$excounter = $exclusions.Count
write-host “Files to not delete $excounter”
Connect-PnPOnline -Url $siteurl -Credentials $O365Credential
$items = Get-PnPFolderItem -FolderSiteRelativeUrl "/Picture Folder/Test" -ItemType File
$ListItemCount = $items.Count
Write-Host $ListItemCount
$Found = 0
foreach ($item in $items)
{
foreach ($User in $exclusions)
{
#Write-Host $item.Name " " $User.User
if ($item.Name -eq $User.User)
{
# Write-Host $item.Name " " $User.User
$Found = 1
}
}
if($Found -eq 0)
{
$Name = $item.Name
Write-host "Delete: " $item.Name $Found
$item.DeleteObject()
}
$Found=0
}
I'm hoping to delete photos, that are not on the exclusions list.
Instead of:
$item.DeleteObject()
Use:
Remove-PnPFile -ServerRelativeUrl $item.ServerRelativeURL
Docs:
https://pnp.github.io/powershell/cmdlets/Remove-PnPFile.html

Powershell uploading files to SharePoint : Exception calling "ExecuteQuery" with "0" argument(s) error

I want to upload all .csv files from a C:/ to SharePoint. The script runs up to $Ctx.ExecuteQuery() and returns this error. I am able to run other PowerShell scripts on the site, and am the site owner, I suspect it is something other than access privileges.
Where do I start looking ?
Exception calling "ExecuteQuery" with "0" argument(s): "The remote server returned an error: (403) Forbidden."
+ $Ctx.ExecuteQuery()
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
Get-ChildItem "c:\users\xxx\downloads" -Filter *.csv | % {
$eachFile =Get-ChildItem "c:\users\xxxx\downloads\" -Filter *.csv
$eachFile | ForEach-Object{
#parameters
$SiteURL = "https://xxx.sharepoint.com/sites/nrg"
$LibraryName="Audit History"
$UserName = "xxxx#x.onmicrosoft.com"
$Password = "xx"
$SecurePassword= $Password | ConvertTo-SecureString -AsPlainText -Force
#Setup the Context
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$Cred = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword)
$Ctx.Credentials = $Credentials
#Get the Library
$Library = $Ctx.Web.Lists.GetByTitle($LibraryName)
#Get the file from disk
$FileStream = ([System.IO.FileInfo] (Get-Item $OutputFile)).OpenRead()
#Get File Name from source file path
$SourceFileName = Split-path $eachFile -leaf
#sharepoint online upload file powershell
$FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
$FileCreationInfo.Overwrite = $true
$FileCreationInfo.ContentStream = $FileStream
$FileCreationInfo.URL = $SourceFileName
$FileUploaded = $Library.RootFolder.Files.Add($FileCreationInfo)
#powershell upload single file to sharepoint online
$Ctx.Load($FileUploaded)
$Ctx.ExecuteQuery()
#Close file stream
$FileStream.Close()
write-host "File has been uploaded!"
}
}
Solution was to remove the Credentials to before the ForEach-Object.

Uploading documents to Sharepoint with Powershell -

The script exports to a CSV and the files need to be uploaded to SharePoint online.
The export works perfectly
Document is renamed to exclude "#mycompany.com"
The error I get is :
Exception calling "ExecuteQuery" with "0" argument(s): "The remote server returned an error: (403) Forbidden."
At line:46 char:9
+ $Context.ExecuteQuery()
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
Get-ChildItem 'c:\users\xxxx\downloads' -Filter *.csv | % {
$eachFile =Get-ChildItem $Outputfile -Filter *.csv
$eachFile | ForEach-Object{
#Upload Variables - Admin Heidi
[string]$AdminName = "hxxn#xxx.onmicrosoft.com"
[string]$AdminPassword = "Cxx1"
#Upload Credentials
[SecureString]$SecurePass = ConvertTo-SecureString $AdminPassword -AsPlainText -Force
$credentials = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $AdminName, $(convertto-securestring $AdminPassword -asplaintext -force)
$AdminSiteURL="https://nrcl.sharepoint.com"
#Site report will be stored on SharePoint
$SiteURL="https://xxx.sharepoint.com/sites/nrg/"
$LibraryName="Audit History"
#Set up the context
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$Context.Credentials = $Credentials
#Get the Library
$Library = $Context.Web.Lists.GetByTitle($LibraryName)
#Get the file from c:/
$FileStream = ([System.IO.FileInfo] (Get-Item $OutputFile)).OpenRead()
#Get File Name from source file path
$SourceFileName = Split-path $eachFile -leaf
#sharepoint online upload file powershell
$FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
$FileCreationInfo.Overwrite = $true
$FileCreationInfo.ContentStream = $FileStream
$FileCreationInfo.URL = $SourceFileName
$FileUploaded = $Library.RootFolder.Files.Add($FileCreationInfo)
#powershell upload single file to sharepoint online
$Context.Load($FileUploaded)
#######--------fails after this line ---------------#####
$Context.ExecuteQuery()
#Close file stream
$FileStream.Close()
write-host "File has been uploaded!"
}

How to Update the Modified By and Created By fields using PnP

I'm trying to upload a fileshare from my local machine to SharePoint using Add-PnPFile, i also have csv that has all the properties("Modified By", "Created By") for each file.
I have written this code below to grab the all the properties of the files from a csv document and tested to see if the user existed in the tenant before the using the Add-PnPFile command to upload the file.
Function Upload-Nom{
Param (
[parameter(Position=0,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
[Alias('FullName')]
[string[]]$Path = $PWD
)
Begin {}
Process {
ForEach ($item in $Path) {
#iterate all the file urls in the csv
Import-Csv $item | ForEach-Object {
#capture all the properties you need to update the file properties on sharepoint
$name = $_.Name
$fullName = $_.FullName
$itemtype = $_.'Item Type'
$relativepath = $_.Path -replace '(sites\/honours\/)'
$modifiedbyuser = $_.'Modified By'
$createdbyuser = $_.'Created By'
$modified = $_.Modified
$path = $_.Path -replace '\/','\'
$path = $path -replace '(sites\\honours\\)'
$fullurl ="C:\Users\modonny\Downloads\" +$path+"\"+ $name
#convert dates to SP format
[DateTime]$dateformats = New-Object System.DateTime;
if([DateTime]::TryParse($_.Modified, [ref]$dateformats)){
$cdob = $dateformats;
}
$modifieduser = Get-PnPUser | ? Title -eq $modifiedbyuser
$createduser = Get-PnPUser | ? Title -eq $createdbyuser
#check if user exists in tenancy
if($modifieduser){
$muserid = $modifiedbyuser.Email
}else{
$muserid = "john.doe#test.gov.uk"
}
if($createduser){
$cuserid = $createduser.Email
}else{
$createduser = Get-PnPUser | ? Email -EQ "john.doe#test.gov.uk"
$cuserid = "john.doe#test.gov.uk"
}
$object = #{}
$object.Add("Modified",$cdob)
$object.Add("Editor" ,$muserid)
$object.Add("Author" ,$cuserid)
if($fullurl | Test-Path){
if($itemtype -eq 'Folder'){
write-host "this item is a folder"
}else{
#upload files to sharepoint with the data in the $object variable
Add-PnPFile -Path $fullurl -Folder $relativepath -Values $object
}
}
}
}
}
Upload-Nom -Path "C:\Users\modonny\Documents\testing.csv"
When the code completes running all files are uploaded but the Modified By/Created By property isn't.
Sample script for your reference.
#region Variables
$Username = "user#tenant.onmicrosoft.com"
$Password = "password"
$siteURL = "https://tenant.sharepoint.com/sites/Community"
#endregion Variables
#region Credentials
[SecureString]$SecurePass = ConvertTo-SecureString $Password -AsPlainText -Force
[System.Management.Automation.PSCredential]$PSCredentials = New-Object System.Management.Automation.PSCredential($Username, $SecurePass)
#endregion Credentials
Connect-PnPOnline -Url $siteURL -Credentials $PSCredentials
$user=Get-PnPUser | ? Email -eq "user1#tenant.onmicrosoft.com"
Add-PnPFile -Path "C:\Lee\test.docx" -Folder "MyDoc" -Values #{Editor=""+$user.Id+"";Modified="7/24/2019"}

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