Problem with code in Sharepoint/Powershell - powershell

So here's my problem,
We want to automate the copy of notepad (Sharepoint) in my company,
We already have the power-automate script which allows us to copy links from sharepoint sites,
And here is the Power shell code which allows you to recover the site files and copy them to another:
$SiteURL = "https://******.sharepoint.com/sites/********"
$TargetFolderURL = "/sites/*********/*****"
$SitestoCopy = "copy"
Connect-PnPOnline -Url $SiteURL -UseWebLogin
$items = Get-PnPListItem -List $SitestoCopy
Write-Host "Nombre total d'éléments :" $items.Count
ForEach ($item in $items)
{
Write-Host $item["Title"]
#Copy All Files and Folders from one folder to another
Copy-PnPFile -SourceUrl $item["Title"] -TargetUrl $TargetFolderURL -SkipSourceFolderName -Force
}
I have an error : Copy-PnPFile : File not found.
i have no clue to resolve this problem,
Anyone could help me?
Thank you

I think the problem is in the -SourceUrl param. You pass the item Title. According to the spec this should be the relative url to the item. I am not sure now in what column it was stored I am guessing something like "ServerRelativeUrl" or "FileRef". Please try to check it out and change it to correct column to pass the url to the item not the title.
I hope it will be of any help :)

SourceUrl should be the file server relative url, use FileRef instead,
TargetUrl should be TargetFolderURL +filename
Modify the code snippet as below:
$SiteURL = "https://Tenant.sharepoint.com/sites/dev"
$TargetFolderURL = "/sites/dev/docs/"
$SitestoCopy = "copy"
Connect-PnPOnline -Url $SiteURL -UseWebLogin
$items = Get-PnPListItem -List $SitestoCopy
Write-Host "Nombre total d'éléments :" $items.Count
ForEach ($item in $items)
{
$TargetFileUrl=$TargetFolderURL+$item["FileLeafRef"]
#Copy All Files and Folders from one folder to another
Copy-PnPFile -SourceUrl $item["FileRef"] -TargetUrl $TargetFileUrl -SkipSourceFolderName -Force
}

Related

Delete (SP2019 on Prem) Site with SubSite(s)

(FIRST POST - I will do my best to summerize, forgive me ahead of time)
I have a SharePoint site with a list of sites to be deleted, problem is, some of the sites to be deleted have subsites that need to be deleted before the deletion can occure. I have a basic Powershell script that will delete the site as long as there are no subsites.
I am trying to come up with either a method to delete the subsites if the listed site to be deleted has subs or a way to catch the ones that have an error to enter data into a column on the same list or output a file AND to continue deleting the sites without subs.
Here is what I have so far:
#========================================================================#
# Delete confirmed sites #
#========================================================================#
function deleteSites_old ($url, $listName) {
$web = get-SPWeb $url
$list = $web.Lists[$listname]
$items = $list.items | Where-Object {($_['Status'] -eq 'Delete')}
Write-host "List $($list.title) has $($items.count) entries to be deleted"
foreach ($item in $items) {
$siteURL = $item["URL"]
$siteOwner = $itme["SiteOwner"]
write-host $siteURL $siteOwner
try {
write-host "Site deletion"
#Remove-SPWeb -Identity $siteURL -Recycle
}
catch [Microsoft.SharePoint.Powershell.SPCmdRemoveWeb] {
"There was a problem deleting web site $($siteURL)"
}
#Remove-SPWeb -Identity $siteURL -Recycle
#$ListItem["Status"] = "DELETED"
#$ListItem.update()
}
#DELETES THE INSTANCE
$web.Dispose()
}
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
$Site = '[URL]'
$list = "[List Name]"
 
deleteSites_old $Site $List
I am still testing so I have commented out as I continue. Thanks ahead of time, I did search the forum first but only found questions related to SPOnline or SP13 (with $ChildSites but couldn't get it to work for my environment)

Recursively Upload Large Files Via PNP-Powershell to Sharepoint Online Using Large Chunks

I have some files that I need to keep in sync with my SharePoint Document Library. The problem is some of the files are over the 250mb limit the code I currently have works but only for files under that 250mb limit. I cannot figure out how to upload the same recursive files I need to SharePoint using the same code and large chunks? It seems that what I need to integrate is option 3 of this page -> LARGE FILE HANDLING - OPTION 3 (StartUpload, ContinueUpload and FinishUpload) also it seems that if (Test-Path($topSPOFolder+"\"+$aFileName.FullName)) is not checking the target directory if a file exists to skip and move on. Any help is always appreciated.
$password = ConvertTo-SecureString "test123" -AsPlainText -Force
$username = "abc#def.com"
$cred = New-Object System.Management.Automation.PSCredential ($username, $password)
$makeUrl ="https://helloworld.sharepoint.com/sites/helloworld"
$sourcePath = "\\1.2.3.4\e$\MSI\packages\*\*.msi";
$topSPOFolder = "Shared Documents\packages\test";
# install pnp powershell..?
#Install-Module SharePointPnPPowerShellOnline
# connect to spo online
Connect-PnPOnline -Url $makeUrl -Credentials $cred
$fileNames = Get-ChildItem -Path $sourcePath -Recurse ;
foreach($aFileName in $fileNames)
{
if($aFileName.GetType().Name -ne "DirectoryInfo")
{
if (Test-Path($topSPOFolder+"\"+$aFileName.FullName))
{
Write-Host 'Skipping file, already downloaded' -ForegroundColor Yellow
return
} else {
$fn=$topSPOFolder;
Add-PnPFile -Path $aFileName.FullName -Folder $fn;
$fn=$null
}
}
}

Getting 'created by' for a folder in Sharepoint document library

I want to get the author(who created) a folder in a Sharepoint Online using PnP PowerShell. The time last modified I can get it, but the field author I cannot get it. I know that can be two different fields, author and modifier, but I cannot get any from this.
For the folders:
$folder = Get-PnPFolderItem -FolderSiteRelativeUrl $folderPath -ItemName $subfolderName
Write-Host "URL : " $folder.ServerRelativeUrl
Write-Host "Name : " $folder.Name
Write-Host "Modified : " $folder.TimeLastModified
# above are ok, but $folder has no author property
# same next line fails, Author it does not exist
$folder= Get-PnPFolder -Url "$folderPath/$subfolderName" -Includes ListItemAllFields.Author
For the files, is easy I use:
Get-PnPFile -ServerRelativeUrl $file.ServerRelativeUrl -Path $destinationfolder -FileName $file.Name -AsFile
$f = Get-PnPFile -Url "$($folderUrl)/$($file.Name)" -AsListItem
$fileDetails = #{
File = "$($destinationFolder)/$($file.Name)"
Author = $f["Author"].Email
Created = $f["Created"]
}
I just find the solution, if anyone need:
context = Get-PnPContext
$context.load($context.Web)
$context.ExecuteQuery()
$list = $context.Web.Lists.GetByTitle("Documente")
$context.Load($list)
$context.ExecuteQuery()
$camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery
$camlQuery.ViewXml ="<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='FileRef' /><Value Type='Text'>/server/folder/relativepath</Value></Eq></Where></Query></View>";
$allItems=$list.GetItems($camlQuery)
$context.Load($allItems)
$context.ExecuteQuery()
foreach($item in $allItems){
Write-Host "##############"
Write-Host $item["FileRef"]
$item["Author"].Email
$item["Modified"]
}

How to use Get-PnPFolder to show SharePoint folder perm

I am using PowerShell PNP to try and read the permissions of a folder but the command Get-PnPFolder does not appear to include the permissions.
I tried the code listed here but the permissions collection are empty. https://sharepoint.stackexchange.com/questions/221118/retrieve-permissions-at-folder-and-file-level-in-powershell/221513 . This small sample below is what I used for testing.
$spserver = 'https://myportal.sharepoint.com/sites/mysite/'
Connect-PnPOnline –Url $spserver –UseWebLogin
$foldername = 'myFormLibraryName'
$folderObj = Get-PnPFolder -Url $foldername -Includes ListItemAllFields.RoleAssignments, ListItemAllFields.HasUniqueRoleAssignments
$folderObj.ListItemAllFields.HasUniqueRoleAssignments
$folderObj.ListItemAllFields.RoleAssignments
The results of the code will return "collection has not been initialized". How do I get a list of the permissions for a SharePoint folder?
I was not able to get the code to work with Get-PnPFolder and used the code below as an alternative.
$spserver = 'https://myportal.sharepoint.com/sites/mysite/'
Connect-PnPOnline –Url $spserver –UseWebLogin
$ctx=Get-PnPContext
$foldername = 'Documents'
$web = $ctx.Web
$list = $ctx.Site.RootWeb.Lists.GetByTitle($foldername)
$ctx.Load($list)
$ctx.ExecuteQuery()
Write-Host 'count is ' $list.ItemCount
$roleass = $list.RoleAssignments
$ctx.Load($roleass)
$ctx.ExecuteQuery()
Write-Host 'loaded'
foreach($rol in $roleass) {
$ctx.Load($rol.Member)
$ctx.ExecuteQuery()
Write-Host $rol.Member.Title
}

How to use PowerShell to download files from SharePoint?

I've used the following sites to help me get this far and to troubleshoot.
Download file from SharePoint
How to download newest file from SharePoint using PowerShell
Mike Smith's Tech Training Notes SharePoint, PowerShell and .Net!
Upload file to a SharePoint doc library via PowerShell
Download latest file from SharePoint Document Library
How to iterate each folders in each of the SharePoint websites using PowerShell
PowerShell's Get-ChildItem on SharePoint Library
I am trying to download random files from SharePoint folder, and I have it working for when I actually know the file name and extension.
Working code with name and extension:
$SharePoint = "https://Share.MyCompany.com/MyCustomer/WorkLoad.docx"
$Path = "$ScriptPath\$($CustomerName)_WorkLoad.docx"
#Get User Information
$user = Read-Host "Enter your username"
$username = "$user#MyCompany"
$password = Read-Host "Enter your password" -AsSecureString
#Download Files
$WebClient = New-Object System.Net.WebClient
$WebClient.Credentials = New-Object System.Net.Networkcredential($UserName, $Password)
$WebClient.DownloadFile($SharePoint, $Path)
However, I don't seem to be able to figure out how to do it with multiple files of unknown names or extensions.
I have tried mapping a drive, only to end up with "drive mapping failed" & "The network path was not found." errors:
$SharePoint = Read-Host 'Enter the full path to Delivery Site'
$LocalDrive = 'P:'
$Credentials = Get-Credential
if (!(Test-Path $LocalDrive -PathType Container)) {
$retrycount = 0; $completed = $false
while (-not $completed) {
Try {
if (!(Test-Path $LocalDrive -PathType Container)) {
(New-Object -ComObject WScript.Network).MapNetworkDrive($LocalDrive,$SharePoint,$false,$($Credentials.username),$($Credentials.GetNetworkCredential().password))
}
$Completed = $true
}
Catch {
if ($retrycount -ge '5') {
Write-Verbose "Mapping SharePoint drive failed the maximum number of times"
throw "SharePoint drive mapping failed for '$($SharePoint)': $($Global:Error[0].Exception.Message)"
} else {
Write-Verbose "Mapping SharePoint drive failed, retrying in 5 seconds."
Start-Sleep '5'
$retrycount++
}
}
}
}
I've also used the following code with similar results or no results at all.
#Get User Information
$user = Read-Host "Enter your username"
$username = "$user#MyCompany"
$password = Read-Host "Enter your password" -AsSecureString
#Gathering the location of the Card Formats and Destination folder
$Customer = "$SharePoint\MyCustomer"
$Products = "$Path\$($CustomerName)\Products\"
#Get Documents from SharePoint
$credential = New-Object System.Management.Automation.PSCredential($UserName, $Password)
New-PSDrive -Credential $credential -Name "A" -PSProvider "FileSystem" -Root "$SharePoint"
net use $spPath #$password /USER:$user#corporate
#Get PMDeliverables file objects recursively
Get-ChildItem -Path "$Customer" | Where-Object { $_.name -like 'MS*' } | Copy-Item -Destination $Products -Force -Verbose
Without defined "input parameters", it's not exactly clear the full solution you need so I'll provide a few snippets of PowerShell that should be of use based on what you've described.
I'll spare you the basics of the various OOTB functions (i.e. Get-SPWeb, etc) though can provide those details as well if needed. I've also been overly explicit in the scripting, though know some of these lines could be chained, piped, etc to be made shorter & more efficient.
This example will iterate over the contents of a SharePoint Library and download them to your local machine:
$Destination = "C:\YourDestinationFolder\ForFilesFromSP"
$Web = Get-SPWeb "https://YourServerRoot/sites/YourSiteCollection/YourSPWebURL"
$DocLib = $Web.Lists["Your Doc Library Name"]
$DocLibItems = $DocLib.Items
foreach ($DocLibItem in $DocLibItems) {
if($DocLibItem.Url -Like "*.docx") {
$File = $Web.GetFile($DocLibItem.Url)
$Binary = $File.OpenBinary()
$Stream = New-Object System.IO.FileStream($Destination + "\" + $File.Name), Create
$Writer = New-Object System.IO.BinaryWriter($Stream)
$Writer.write($Binary)
$Writer.Close()
}
}
This is pretty basic; the variables up top are where on your local machine you wish to store the download files ($Destination), the URL of your SharePoint Site/Web ($Web) and the name of the Document Library (Your Doc Library Name).
The script then iterates through the items in the Library (foreach ($DocLibItem in $DocLibItems) {}), optionally filters for say items with a .docx file extension and downloads each to your local machine.
You could customize this further by targeting a specific sub-folder within the Doc Library, filter by metadata or properties of the Docs or even iterate over multiple Sites, Webs and/or Libraries in one script, optionally filtering those based on similar properties.