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

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"]
}

Related

Downloading SharePoint online list items' attachments locally will not allow me to open those files (seems the file are corrupted)

I have a SharePoint online list , and this list contain items with attachments. so i want to download all the list item attachems. so i wrote this PnP Power Shell sript:-
$ApprovalListItems = Get-PnPListItem -List "tickets" -PageSize 1000 -ScriptBlock { Param($items) $items.Context.ExecuteQuery()} | ForEach-Object {
$ctx = Get-PnPContext
$spSourceWeb= Get-PnPWeb
$ItemAttachmentURLPrefix = 'https://****.sharepoint.com/Lists/tickets/Attachments/'+$_['ID']+'/'
$attachmentCollection = ForEach-Object{Get-PnPProperty -ClientObject $_ -Property "AttachmentFiles"}
$AttachmentSeq = 0
ForEach($Attachment in $attachmentCollection)
{
Write-Host "`tDownloading Attachement: " $attachment $ItemAttachmentURLPrefix
$AttachmentSeq++
$AttachmentDataObj = "" | Select "Attachment Seq", "JDE Company", "Vendor Number", "Vendor Invoice Number", "Attachment Name", "Attachment System Name", "Job-run Date/Time Stamp"
Write-Host $Attachment.FileName
$file = Get-PnPFile -Url ($ItemAttachmentURLPrefix + $Attachment.FileName)
$bytes = (Get-PnPFile -Url ($ItemAttachmentURLPrefix + $Attachment.FileName)).OpenBinaryStream()
$name = "C:\Attachments\"+$Attachment.FileName
$fs = New-Object System.IO.StreamWriter($name, "OpenOrCreate")
$fs.Write($bytes, 0 , $bytes.Length)
$fs.Close()
$stream = $streamResult.Value
Write-Host $file.Name
Write-Host $stream.Name
}
}
but the files that will get saved can not be opened, for example this excel sheet will raise this error:-
while a pdf will raise this error:-
any advice what is wrong with my script?
Thanks
Use PnP PowerShell code in below format to download list item attachments to local folder:
Connect-PnPOnline -Url https://contoso.sharepoint.com/sites/dev -Interactive
$listitem = Get-PnPListItem -List Employee -Id 2
$attachments = ForEach-Object {Get-PnPProperty -ClientObject $listitem -Property "AttachmentFiles"}
$attachments | ForEach-Object { Get-PnPFile -Url $_.ServerRelativeUrl -FileName $_.FileName -Path "E:\SharePoint\Documents" -AsFile }
Source: Read items attachments and write them to local folder

PowerShell Script uploading file to SharePoint doesn't work when run from Task Scheduler

Overview: I have a script which runs a query to extract all Audit Logs from the past day, from a SharePoint site. It then creates a .csv file, and uploads it to the "Shared Documents" folder on SharePoint.
The script works perfectly when I manually run it from PowerShell console, regardless if it's run with admin rights, or not.
NOTE: This SharePoint solution is On-Premise, not Online.
The Issue: When I run the script from Task Scheduler it generates the .csv file, and completes the whole script, but the file is never uploaded. There's no error messages.
Task Scheduler Settings: I use "Run whether user is logged on or not" and "Run with highest privileges"
Here's the full script:
Start-Transcript -Path "C:\Timer Jobs\exampleDomain.Audit.CreateAndTrimLog\transcript17.txt" -NoClobber
Add-PSSnapin "Microsoft.SharePoint.PowerShell"
#Get date, and format it. Used for file name, and for deleting old Audit files
$today = Get-Date
$startDate = $today.AddDays(-1)
$todayFormatted = $today.ToString('dd-MM/yyyy_HH-mm-ss')
#Get site and save siteURL
$siteUrl = "https://example.com"
$docLibName = "Shared Documents"
#site is needed for Audit Query
$site = Get-SPSite -Identity $siteUrl
#web is needed to upload the file
$web = Get-SPWeb -Identity $siteUrl
$list = $web.Lists[$docLibName]
$folder = $list.RootFolder
$files = $folder.Files
#Creaty query for Audits
$wssQuery = New-Object -TypeName Microsoft.SharePoint.SPAuditQuery($site)
$wssQuery.SetRangeStart($startDate)
$wssQuery.SetRangeEnd($today)
#Create Audit Collection object
$auditCol = $site.Audit.GetEntries($wssQuery)
#Get all users on site
$users = $site.RootWeb.SiteUsers
#Get and add $userName to each $audit
#Ignore when it says "User cannot be found" in log
$CachedUsers = #{};
foreach($audit in $auditCol){
$curUserId = $audit.UserId;
$user = $null;
if($CachedUsers.$curUserId -eq $null){
$user = $users.GetById($curUserId);
$CachedUsers.$curUserUI = $user;
} else {
$user = $CachedUsers.$curUserId;
}
$userName = ($user.DisplayName + " <" + $user.LoginName) + ">";
$audit | Add-Member NoteProperty -Name "UserName" -Value $userName -Force;
}
#Export CSV-file. Save fileName and filePath for when uploading to SharePoint
$fileName = ("domain_Audit_Log_" + $todayFormatted + ".csv")
$filePath = "C:\Users\xml\" + ($fileName)
$auditCol | Export-Csv -Append -path ($filePath) -NoTypeInformation -Delimiter ";" -Encoding UTF8
$file = Get-ChildItem $filePath
[Microsoft.SharePoint.SPFile]$spFile = $web.GetFile("/" + $folder.Url + "/" + $file.Name)
if($spFile.Exists -eq $false) {
#Open FileStream
$fileStream = ([System.IO.FileInfo] (Get-Item $file.FullName)).OpenRead()
#Add File
Write-Host "Uploading file" $file.Name "to" $folder.ServerRelativeUrl "..."
try {
[Microsoft.SharePoint.SPFile]$spFile = $files.Add($folder.Url + "/" + $file.Name, [System.IO.Stream]$fileStream, $true)
Write-Host "Success"
} catch {
Write-Host "Error"
}
#Close FileStream
$fileStream.Close()
}
$web.Dispose()
#$site.Audit.DeleteEntries($startDate)
Only difference in the Transcript.txt file, when I run it Manually vs. Task Scheduler is these lines, that are added in the Task Scheduler Tanscript:
PS>$global:?
True
The Transcript prints the "Success" line from my Try-Catch
Problem was in SharePoint. Whenever I uploaded a file using Task Scheduler the file was marked as "Checked Out", so it was not viewable for other users.

How to search in PDF files and move them using powershell

I have a large number of PDF files in a folder with several subfolders. In this pile of files I need to find the ones with a specific string and move them to a new destination.
I already have a fine piece of code for the search process that gives me the files needed (thx to the creator) - now I need help to combine this code with a move-function. All the files found by the following code should be moved to a new destination.
$searchString = "text i need to find"
$searchPath = "C:\test"
$sql = "SELECT System.ItemPathDisplay, System.DateModified, "
+ "System.Size, System.FileExtension FROM SYSTEMINDEX "
+ "WHERE SCOPE = '$searchPath' AND FREETEXT('$searchstring')"
$provider = "provider=search.collatordso;extended properties=’application=windows’;"
$connector = new-object system.data.oledb.oledbdataadapter -argument $sql, $provider
$dataset = new-object system.data.dataset
if ($connector.fill($dataset)) { $dataset.tables[0] }
The output is like:
SYSTEM.ITEMPATHDISPLAY SYSTEM.DATEMODIFIED SYSTEM.SIZE SYSTEM.FILEEXTENSION
---------------------- ------------------- ----------- --------------------
C:\test\file.pdf 27.08.2019 19:14:57 17119 .pdf
Thank you for your help!
I found a solution by myself. For anyone interested.
Note: $searchPath must be a local drive on the machine you are running the script on, because the PDF files need to be indexed by the windows search. For that you probably have to install an iFilter: https://superuser.com/questions/402673/how-to-search-inside-pdfs-with-windows-search
$searchString = "Merkblatt für nüchtern eintretende Patienten"
$searchPath = "Y:\"
$targetPath = "\\Server\Path\folder"
$sql = "SELECT System.ItemPathDisplay, System.DateModified, " +
"System.Size, System.FileExtension FROM SYSTEMINDEX " +
"WHERE SCOPE = '$searchPath' AND FREETEXT('$searchstring')"
$provider = "provider=search.collatordso;extended properties=’application=windows’;"
$connector = new-object system.data.oledb.oledbdataadapter -argument $sql, $provider
$dataset = new-object system.data.dataset
if ($connector.fill($dataset)) {
#$dataset.tables[0]
foreach ( $Row in $dataset.tables[0].Rows) {
$targetFile = $Row[0] -replace "^Y:", $targetPath
$targetSubfolder = Split-Path -Path $targetFile
#write-host "Targetfile : $targetFile"
#write-host "Moving: $($Row[0])"
Move-Item -Path $($Row[0]) -Destination $targetPath -Force
}
}

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 update the folder property in sharepoint shareddocument folder

Below C# code I have used to update the folder property in shared document, same concept I have tried in PowerShell but I didn't get any clue.
SPFolder newFolder = folders.Add(ParentURL + FolderURL + "/" + FolderName);
//Added Title Property to newFolder
newFolder.AddProperty("vti_title", FolderName);
//newFolder.Update();
In PowerShell:
> $web = Get-SPWeb "http://server/sites/4tmdk9h7qc4g"
> $site=$web $list = $web.Lists["Shared Documents"]
foreach ($item in $list.Folders)
{
write-host $item["Title"]
/?? HOW TO UPDATE HERE
$item.Update()
}
$item is a SPListItem object. Use SPListItem.Folder to access the SPFolder object:
$item.Folder
Finally this code loop all the site document folder and updated the title
$inputUrl =Read-Host "Enter the site URL"
$site = Get-SPSite -identity $inputUrl
$site | Get-SPWeb -limit |ForEach-Object
{
$web = Get-SPWeb $_.Url
$list =$web.lists["Shared Documents"]
Write-Host $_.Url
foreach($item in $list.folders)
{
$item["Title"]="ayyappan"
$item.update()
Write-Host $item["Title"]
}
}