Add person to person field sharepoint - powershell

Currently I have this script as test:
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName(“System.Web”) | Out-Null
$User = 'usernamehere'
$Pass = ConvertTo-SecureString 'passwordhere' -AsPlainText -Force
$SPOUrl = "sharepointlisthere"
$SPOList = "Add2AD"
$SPListItemColumns = #{
FirstName = "Title"
LastName = "Achternaam"
Title = "Functie"
Managerf = "Teamleider"
Status = "Status"
Mail = "Mail"
Laptop = "Laptop"
Accountnaam = "Accountnaam"
}
#Connect to SharePoint Online
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($SPOUrl)
$Context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($User, $Pass)
#Get the list
$List = $Context.Web.Lists.GetByTitle($SPOList)
$Query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery(100)
$Items = $List.GetItems($Query)
$Context.Load($Items)
$Context.ExecuteQuery()
foreach($item in $Items)
{
#Get list item for later reference
$ListItem = [Microsoft.SharePoint.Client.ListItem]$listItem = $List.GetItemById($Item.FieldValues["ID"])
if ($item.FieldValues[$SPListItemColumns.Status] -eq "Nee") {
Write-Verbose "Processing list item $Firstname $LastName with ID=$($item.FieldValues["ID"])"
#Put the fieldvalues in variables.
$Managerf = $item.FieldValues[$SPListItemColumns.Managerf]
$Managerf = $Managerf.LookupValue
Write-Output $Managerf
$ListItem[$SPListItemColumns.Accountnaam] = "sgouman#test.nl"
$ListItem.Update()
$Context.ExecuteQuery()
}
}
But whenever I run this script I get this error:
Exception calling "ExecuteQuery" with "0" argument(s): "There are invalid data used to update this listitem or the field is readonly."
so what could it be? I already tried with the user as email address and user as just the normal name none of these work. I want to update the name that is in office 365 so we can later use that field to email them.

Related

SharePoint Online & PNP PowerShell - output a libraries documents to CSV within all metadata, including CONTENT TYPE

I have been using the following to output as a CSV a SharePoint Online document library, including all custom metadata field properties.
I however cannot obtain the assigned Content Type. I am treating as a standard column, but imagine there is more to it? I don't seem to be able to find anything relevant.
#Parameters
$SiteURL = "https://SHAREPOINT URL"
$ListName= "LIBRARYNAME"
$ReportOutput = "C:\LOCATION.csv"
$Pagesize = 500
#Connect to SharePoint Online site
Connect-PnPOnline $SiteURL -UseWebLogin
#Delete the Output report file if exists
If (Test-Path $ReportOutput) { Remove-Item $ReportOutput}
#Array to store results
$Results = #()
#Get all Documents from the document library
$List = Get-PnPList -Identity $ListName
$global:counter = 0;
$ListItems = Get-PnPListItem -List $ListName -PageSize $Pagesize -Fields Author, Editor, Created, File_x0020_Type, Business_x0020_Unit, Department, Device, Document_x0020_Type, Employee_x0020_Status, Retention_x0020_Period, Scan_x0020_Date, Scanned_x0020_by, Staff_x0020_ID, Staff_x0020_Name, ContentType -ScriptBlock `
{ Param($items) $global:counter += $items.Count; Write-Progress -PercentComplete ($global:Counter / ($List.ItemCount) * 100) -Activity `
"Getting Documents from Library '$($List.Title)'" -Status "Getting Documents data $global:Counter of $($List.ItemCount)";} | Where {$_.FileSystemObjectType -eq "File"}
$ItemCounter = 0
#Iterate through each item
Foreach ($Item in $ListItems)
{
$Results += New-Object PSObject -Property ([ordered]#{
Name = $Item["FileLeafRef"]
Type = $Item.FileSystemObjectType
FileType = $Item["File_x0020_Type"]
RelativeURL = $Item["FileRef"]
CreatedByEmail = $Item["Author"].Email
CreatedOn = $Item["Created"]
Modified = $Item["Modified"]
ModifiedByEmail = $Item["Editor"].Email
BusinessUnit = $Item["Business_x0020_Unit"]
Department = $Item["Department"]
Device = $Item["Device"]
DocumentType = $Item["Document_x0020_Type"]
EmployeeStatus = $Item["Employee_x0020_Status"]
RetentionPeriod = $Item["Retention_x0020_Period"]
ScanDate = $Item["Scan_x0020_Date"]
ScannedBy = $Item["Scanned_x0020_by"]
StaffID = $Item["Staff_x0020_ID"]
StaffName = $Item["Staff_x0020_Name"]
ContentType = $Item["ContentType"]
})
$ItemCounter++
Write-Progress -PercentComplete ($ItemCounter / ($List.ItemCount) * 100) -Activity "Exporting data from Documents $ItemCounter of $($List.ItemCount)" -Status "Exporting Data from Document '$($Item['FileLeafRef'])"
}
#Export the results to CSV
$Results | Export-Csv -Path $ReportOutput -NoTypeInformation
Write-host "Document Library Inventory Exported to CSV Successfully!"
Any pointers on how I can capture the involved Content Type of the library items welcomed!
Try this:
$ctx = Get-PnPContext
Foreach ($Item in $ListItems)
{
$Ctx.Load($Item.ContentType)
$Ctx.ExecuteQuery()
write-host $Item.ContentType.Name
}
Test result:
Updated:
$ctx = Get-PnPContext
Foreach ($Item in $ListItems)
{
$Ctx.Load($Item.ContentType)
$Ctx.ExecuteQuery()
$Results += New-Object PSObject -Property ([ordered]#{
Name = $Item["FileLeafRef"]
Type = $Item.FileSystemObjectType
FileType = $Item["File_x0020_Type"]
RelativeURL = $Item["FileRef"]
CreatedByEmail = $Item["Author"].Email
CreatedOn = $Item["Created"]
Modified = $Item["Modified"]
ModifiedByEmail = $Item["Editor"].Email
BusinessUnit = $Item["Business_x0020_Unit"]
Department = $Item["Department"]
Device = $Item["Device"]
DocumentType = $Item["Document_x0020_Type"]
EmployeeStatus = $Item["Employee_x0020_Status"]
RetentionPeriod = $Item["Retention_x0020_Period"]
ScanDate = $Item["Scan_x0020_Date"]
ScannedBy = $Item["Scanned_x0020_by"]
StaffID = $Item["Staff_x0020_ID"]
StaffName = $Item["Staff_x0020_Name"]
ContentType = $Item.ContentType.Name
})

Use powershell to delete Sharepoint online list item

I currently have a powershell script to loop through a list on an Sharepoint online site.
$creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials("[USERNAME]", (ConvertTo-SecureString "[PASSWORD]" -AsPlainText -Force))
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext("https://[SITENAME].sharepoint.com/sites/Projekter")
$ctx.credentials = $creds
try{
$lists = $ctx.web.Lists
$list = $lists.GetByTitle("Ekstern synkronisering")
$listItems = $list.GetItems([Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery())
$ctx.load($listItems)
$ctx.executeQuery()
foreach($listItem in $listItems)
{
$internal = $listItem["ConnectionString1"]
$external = $listItem["ConnectionString2"]
$folder = $listItem["Mappe"]
$project = $listItem["Project"]
$caseNo = $listItem["Title"]
$doc = New-Object System.Xml.XmlDocument
$doc.Load("C:\Script\PS-Layer2\xmlTemplate.xml")
$ns = New-Object System.Xml.XmlNamespaceManager($doc.NameTable)
$ns.AddNamespace("ns", $doc.DocumentElement.NamespaceURI)
$doc.SelectSingleNode("//ns:dataEntity[#name='Intern site']", $ns).connectionString = $internal+";Authentication=Office365;User Id=$userId;Password=$pwd;"
$doc.SelectSingleNode("//ns:dataEntity[#name='Externt site']", $ns).connectionString = $external+";Authentication=Office365;User Id=$userId;Password=$pwd;"
$doc.Save("C:\Temp\$caseNo - $project - $folder.xml")
}
}
catch{
write-host "$($_.Exception.Message)" -foregroundcolor red
}
This works fine to get the items and modify an XML file..
What I would like to do is, when the XML file has been created, it shall delete the listitem from the sharepoint site, so that it will not be created on the next run again.
Does anyone have a solution on that?
Best regards...

SharePoint Online Powershell Folder creation

I need to be able to script folder creation from a csv into a SharePoint Online document library with each folder with permission inheritance disabled and for different user to each folder to be added.
The following code can create the folders and disable the inheritance but it seems to try add a group but not a user. How to make it add a user instead?
Thanks.
### Get the user credentials
$credential = Get-Credential
$username = $credential.UserName
$password = $credential.GetNetworkCredential().Password
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
### Input Parameters
$url = 'URL HERE'
$csvfilepath='C:\Scripts\data.csv'
$libname ='BUS61'
### References
# Specified the paths where the dll's are located.
Add-Type -Path 'C:\Scripts\SPOCmdlets\Microsoft.SharePoint.Client.dll'
Add-Type -Path 'C:\Scripts\SPOCmdlets\Microsoft.SharePoint.Client.Runtime.dll'
### CreateFolder with Permissions Function
function CreateFolderWithPermissions()
{
# Connect to SharePoint Online and get ClientContext object.
$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($url)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword)
$clientContext.Credentials = $credentials
Function GetRole
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true, Position = 1)]
[Microsoft.SharePoint.Client.RoleType]$rType
)
$web = $clientContext.Web
if ($web -ne $null)
{
$roleDefs = $web.RoleDefinitions
$clientContext.Load($roleDefs)
$clientContext.ExecuteQuery()
$roleDef = $roleDefs | Where-Object { $_.RoleTypeKind -eq $rType }
return $roleDef
}
return $null
}
# Get the SharePoint web
$web = $clientContext.Web;
$clientContext.Load($web)
#Get the groups
$groups = $web.SiteGroups
$clientContext.Load($groups)
$clientContext.ExecuteQuery()
#Read CSV File and iterate
$csv = Import-CSV $csvfilepath
foreach ($row in $csv)
{
#Create Folder
$folder = $web.Folders.Add($libname + "/" + $row.Folder)
$clientContext.Load($folder)
$clientContext.ExecuteQuery()
#Assign Role
$group = $groups.GetByName($row.Group)
$clientContext.Load($group)
$clientContext.ExecuteQuery()
$roleType= $row.Role
$roleTypeObject = [Microsoft.SharePoint.Client.RoleType]$roleType
$roleObj = GetRole $roleTypeObject
$usrRDBC = $null
$usrRDBC = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($clientContext)
$usrRDBC.Add($roleObj)
# Remove inherited permissions
$folder.ListItemAllFields.BreakRoleInheritance($false, $true)
$clientContext.Load($folder.ListItemAllFields.RoleAssignments.Add($group, $usrRDBC))
$folder.Update()
$clientContext.ExecuteQuery()
# Display the folder name and permission
Write-Host -ForegroundColor Blue 'Folder Name: ' $folder.Name ' Group: '$row.Group ' Role: ' $roleType;
}
}
#Execute the function
CreateFolderWithPermissions
Let's assume that you will define user login in your CSv file. Than you have to change the line:
$group = $groups.GetByName($row.Group)
to
$user = $web.EnsureUser($row.User)
and replace all references to $group variable with $user
More generic approach for searching for a user (with for example display name) would be using Utility.ResolvePrincipal method:
[Microsoft.SharePoint.Client.Utilities.Utility]::ResolvePrincipal($clientContext, $web, "DisplayName", ([Microsoft.SharePoint.Client.Utilities.PrincipalType]::User), ([Microsoft.SharePoint.Client.Utilities.PrincipalSource]::All), $null, $false)

Opening a SSRS project using Powershell

I have a report that is copied to a number of different servers. It is imported manually and the data source properties are altered to match the current server's specs. I would like to be able to automate the process by enabling users to open a the SSRS report and dynamically alter it's shared data source properties through PowerShell. I hope you could help. You may see reference below.
The script would accept an input parameter for servername, username and password. Also, the save my password must be ticked.
I couldn't believe I managed to create a script for this. You may make use of the script below as future reference. Comments are available for each part and anything that needs to be altered has a "here" keyword , ex. Your_database_name_here .
Import-Module SqlPs
#Input parameter to get Server\Instancename of your Datasource
$Servername = Read-Host "Please enter your Servername"
$Instancename = Read-Host "Please enter your Instancename. For default instance please press enter"
Write-host ""
if ($Instancename -eq ""){
$ServerInstance = $Servername
}
Else {
$ServerInstance = $Servername +"\"+ $InstanceName
}
#Setting up SSRS Target URL. This is the location where your reports would be deployed.
if ($Instancename -eq ""){
$ReportServerUri = "http://$Servername/ReportServer//ReportService2010.asmx?wsdl"
$TargetURL = "http://$Servername/Reports"
}
Else {
$ReportServerUri = "http://$Servername/ReportServer_$Instancename//ReportService2010.asmx?wsdl"
$TargetURL = "http://$Servername/Reports_$Instancename"
}
$global:proxy = New-WebServiceProxy -Uri $ReportServerUri -UseDefaultCreden
#We would make use of SQL Server Authentication for the reports shared datasource so you need to supply a username and password.
Write-Host " SQL Server Authentication:"
$Username = Read-Host " Username"
$Password = Read-Host -AsSecureString "Password"
$type = $Proxy.GetType().Namespace
$datatype = ($type + '.Property')
$property =New-Object ($datatype);
$property.Name = “NewFolder”
$property.Value = “NewFolder”
$numproperties = 1
$properties = New-Object ($datatype + '[]')$numproperties
$properties[0] = $property;
$newFolder = $proxy.CreateFolder("Reports”, “/”, $properties);
$newFolder = $proxy.CreateFolder("Data Sources”, “/”, $properties);
$Children =$proxy.ListChildren("/",$false)
$DBname = 'Your_Database_Name_Here'
# Creating Datasource through powershell
Write-Host " Creating Datasource ..."
$Name = "Name_Your_Datasource_here"
$Parent = "/Data Sources"
$ConnectString = "data source=$Servername\$Instancename;initial catalog=$DBname"
$type = $Proxy.GetType().Namespace
$DSDdatatype = ($type + '.DataSourceDefinition')
$DSD = new-object ($DSDdatatype)
if($DSD -eq $null){
Write-Error Failed to create data source definition object
}
$CredentialDataType = ($type + '.CredentialRetrievalEnum')
$Cred = new-object ($CredentialDataType)
$CredEnum = ($CredentialDataType).Integrated
$Cred.value__=1
$DSD.CredentialRetrieval =$Cred
$DSD.ConnectString = $ConnectString
$DSD.Enabled = $true
$DSD.EnabledSpecified = $false
$DSD.Extension = "SQL"
$DSD.ImpersonateUserSpecified = $false
$DSD.Prompt = $null
$DSD.WindowsCredentials = $false
$DSD.UserName = $Username
$DSD.Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))
$newDSD = $proxy.CreateDataSource($Name,$Parent,$true,$DSD,$null)
#Deploying RLD files to Target URL
Write-Host " Deploying RDL files ..."
$stream = Get-Content 'D:\Your_RDL_path_here.rdl' -Encoding byte
$warnings =#();
$proxy.CreateCatalogItem("Report","Report_Name_here","/Reports",$true,$stream,$null,[ref]$warnings)
#Let's make use of the datasource we just created for your RDL files.
$Items = $global:proxy.listchildren("/Data Sources", $true)
foreach ($item in $items)
{
$DatasourceName = $item.Name
$DatasourcePath = $item.Path
}
$RDLS = $global:proxy.listchildren("/Reports", $true)
foreach ($rdl in $rdls)
{
$report = $rdl.path
$rep = $global:proxy.GetItemDataSources($report)
$rep | ForEach-Object {
$proxyNamespace = $_.GetType().Namespace
$constDatasource = New-Object ("$proxyNamespace.DataSource")
$constDatasource.Name = $DataSourceName
$constDatasource.Item = New-Object ("$proxyNamespace.DataSourceReference")
$constDatasource.Item.Reference = $DataSourcePath
$_.item = $constDatasource.Item
$global:proxy.SetItemDataSources($report, $_)
Write-Host "Changing datasource `"$($_.Name)`" to $($_.Item.Reference)"
}
}
#Open a IE browser to view the report.
$IE=new-object -com internetexplorer.application
$IE.navigate2($TargetURL)
$IE.visible=$true
Write-Host ""
Write-Host "You may now view the Reports through the open IE browser."
Write-Host -ForegroundColor Green "**STEP COMPLETED!"

EWS Not returning folder permissions

any ideas as to why this ews managed api in powershell keeps returning a 0 folder count and no permissions? i'm using impersonation, it's returning the folder names but no permissions.
function GetPerms{
param([string]$mailboxaddress)
$enumSmtpAddress = [Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress
$global:service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId($enumSmtpAddress,$mailboxaddress);
$mailbox = New-Object Microsoft.Exchange.WebServices.Data.Mailbox($mailboxaddress)
$FolderID = New-Object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$mailbox)
$FolderRoot = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($global:service,$FolderID);
$FolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(10000)
$FolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep
$findfolders = $FolderRoot.FindFolders($FolderView);
foreach ($folder in $findfolders.Folders){
$id = New-Object Microsoft.Exchange.WebServices.Data.FolderId($folder.Id.UniqueId.ToString())
$fld = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($global:service,$id);
$perms = $fld.Permissions
[int]$permcount = $fld.Permissions.Count
write-host $permcount
write-host $fld.Displayname, $fld.Permissions.Count
foreach($f in $fld.Permisions.UserID.PrimarySmtpAddress){
write-host $f
}
for($t=0;$t -le $perms.Count; $t++){
[string]$displayname = $fld.Permissions[$t].UserId.DisplayName
[string]$smtp = $fld.Permissions[$t].UserId.PrimarySmtpAddress
#write-host $mailboxaddress,$fld.DisplayName,$smtp
}
}
}
You need request that Exchange return the Folder Permissions with a PropertySet eg
$psPropset= new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$psPropset.Add([Microsoft.Exchange.WebServices.Data.FolderSchema]::Permissions)
$fld = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($global:service,$id,$psPropset);
And that should then return the permissions
Cheers
Glen