Getting a FieldLookupValue from Sharepoint in Powershell - powershell

Looking on the net I came up with this 2 functions to request Sharepoint using this 3 DLL with powershell :
Microsoft.SharePoint.Client.dll
Microsoft.SharePoint.Client.Taxonomy.dll
Microsoft.SharePoint.Client.Runtime.dll
This function is used to get all items from a list
Function Get-ListItems([Microsoft.SharePoint.Client.ClientContext]$Context, [String]$ListTitle) {
$list = $Context.Web.Lists.GetByTitle($listTitle)
$qry = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery()
$items = $list.GetItems($qry)
$Context.Load($items)
$Context.ExecuteQuery()
return $items
}
And this one to work the list :
Function getChangeListsFromSharepoint(){
$context = New-Object Microsoft.SharePoint.Client.ClientContext($Url)
$items = Get-ListItems -Context $context -ListTitle $listName
foreach($item in $items)
{
/** Working HERE **/
}
$context.Dispose()
}
Now when I'm displaying all item content using Write-Host $item.Fields I've got something like this :
[Title,"blabla"]
...
[SpecialField,Microsoft.SharePoint.Client.FieldLookupValue[]]
[OtherField,Microsoft.SharePoint.Client.FieldLookupValue]
I'm trying to get the value of SpecialField and OtherField. To do so I'm using $item["SpecialField"].LookupValue. And I've got no problem. But when I'm doing it on OtherField the value is empty. If I try to use $item["OtherField"].LookupID the value is not empty and I've got an ID. How can I get the value behind this ID ? What's the difference between FieldLookupValue[] and FieldLookupValue ?

FieldLookupValue[] is a multi-value lookup column.
It has property Allow multiple values set to true and contains an array of items.
So, $item["OtherField"].LookupValue will not work here, you need to iterate it over as below:
#multi-value lookup
$mvLookup = [Microsoft.SharePoint.Client.FieldLookupValue[]] $item["OtherField"]
$mvLookup |% { "Lookup Value: $($_.LookupId):$($_.LookupValue)" }
which results in values as below:
FieldLookupValue is a single value lookup column. It has the Allow multiple values set to false and contains a single item. So, $item["SpecialField"].LookupValue will work here

So the solution was easy : my user didn't had the rights to explore the (field)list because it was from a (sharepoint)list on wich he didn't had any rights. What is strange is that on the website the value was visible but it's not when using powershell.

Related

PowerShell - attempting to build a variable based on concatenated string + PSObject member values

Good day. I am working on an AD computer object creation script that has evolved. I have looked for some ways to dynamically pull data out of a storage object; this started with a hashtable, but then I realized I need multiple "columns" of values so that I could request a 2nd or 3rd value that is stored.
This led me to the creation of some PSObjects. I have a simple array as well.
$SiteCode_SHA = [PSCustomObject]#{
CountryCode = "CH"
SiteCode = "SHA"
ContainerCode = "CHA"
}
$SiteCode_IND = [PSCustomObject]#{
CountryCode = "IN"
SiteCode = "MOB"
ContainerCode = "IND"
}
[array]$ComputerTypeArray = "LT", "PC", "PR"
[string]$SiteCodeInput = (Read-Host -Prompt "Prompt #1 Input Options: SHA, IND")
$ProposedComputerName = '$SiteCode_' + $SiteCodeInput + '.CountryCode'
I am attempting to build a variable that contains the CountryCode from one of the $SideCode_XXX objects, plus the SiteCode from the same object, plus a value from the $ComputerTypeArray (which I am successfully retrieving through Read-Host.)
I have a three character variable that is being input through Read-Host that matches the suffix of the $SiteCode_XXX object. I cannot figure out how to dynamically use the object and its contained values after obtaining input from the user.
Concatenation of texts does not allow me to utilize the PSObject or its contained values, which I expected to be the failure point, but I cannot figure out the standard for getting around this. The goal is to set the variable $ProposedComputerName to "IN" if the $SiteCodeInput is "IND", or "CH" if the $SiteCodeInput is "SHA". (There are other components to the computer name that I am dealing with once this single problem is resolved.)
Thank you for your time.
Instead of using multiple variables, organize your data into a hashtable that use the site code as its key for each entry:
# define the data objects, store them in a simple array
$Sites = #(
[PSCustomObject]#{
CountryCode = "CH"
SiteCode = "SHA"
ContainerCode = "CHA"
}
[PSCustomObject]#{
CountryCode = "IN"
SiteCode = "MOB"
ContainerCode = "IND"
}
)
# now create a hashtable that maps each site code to the corresponding object
$SiteCodeMap = #{}
$Sites |ForEach-Object {
$SiteCodeMap[$_.SiteCode] = $_
}
# ... and now we're ready to take user input
$SiteCodeInput = (Read-Host -Prompt "Prompt #1 Input Options: SHA, IND")
# remember to test whether the input is valid
if($SiteCodeMap.ContainsKey($SiteCodeInput)){
# use valid site code to resolve the corresponding data object and grab the CountryCode value
$ProposedComputerName = $SiteCodeMap[$SiteCodeInput].CountryCode
} else {
Write-Warning "No site with site code '$SideCodeInput' exists!"
}

How to replace/update the Value of an Attribute in LDAP Directory using PowerShell?

The entries in our companys Non-AD LDAP Server look like this:
uid = e145871
sn = Smith
givenName = John
department = Research & Development
department = Human Resource
And so on...
I've developed a PowerShell script to add specific attributes and values which is working just fine. Now I need to replace specific values but the issue is the identical attribute name. (In this case it's "department")
My goal is to replace "Research & Development" with "Something Else". If I run the following script it gets replaced but Human Resource is deleted as well. Is it possible to replace only one value without touching/deleting the other?
$r = New-Object -TypeName System.DirectoryServices.Protocols.ModifyRequest
$r.DistinguishedName = "uid=e145871,ou=identities,ou=users,o=items,dc=company,dc=domain,dc=com"
$DirectoryRequest_value = New-Object "System.DirectoryServices.Protocols.DirectoryAttributeModification"
$DirectoryRequest_value.Name = "department"
$DirectoryRequest_value.Contains("Research & Development")
$DirectoryRequest_value.Operation = [System.DirectoryServices.Protocols.DirectoryAttributeOperation]::Replace
$DirectoryRequest_value.Add("SomethingElse")
$r.Modifications.Add($DirectoryRequest_value)
$result = $connection.SendRequest($r)
Thanks!
The LDAP Replace operation replaces (or overwrites) the entire value of the attribute, including any existing values that might exist as part of a multi-valued attribute.
From RFC4511 ยง4.6 - "Modify Operation":
- operation: Used to specify the type of modification being
performed. Each operation type acts on the following
modification. The values of this field have the following
semantics, respectively:
[...]
replace: replace all existing values of the modification
attribute with the new values listed, creating the attribute
if it did not already exist. A replace with no value will
delete the entire attribute if it exists, and it is ignored
if the attribute does not exist.
Instead, add two separate modifications to the request - one to add "SomethingElse" and one to remove "Research & Development":
$targetObject = 'uid=e145871,ou=identities,ou=users,o=items,dc=company,dc=domain,dc=com'
$attributeName = 'department'
$oldValue = 'Research & Development'
$newValue = 'SomethingElse'
$request = [System.DirectoryServices.Protocols.ModifyRequest]::new()
$request.DistinguishedName = $targetObject
# This modification will add the new value "SomethingElse"
$addNewDepartment = #{
Name = $attributeName
Operation = 'Add'
} -as [System.DirectoryServices.Protocols.DirectoryAttributeModification]
$addNewDepartment.Add($newValue) |Out-Null
$request.Modifications.Add($addNewDepartment) |Out-Null
# This modification will remove the old value "Research & Development"
$removeOldDepartment = #{
Name = $attributeName
Operation = 'Delete'
} -as [System.DirectoryServices.Protocols.DirectoryAttributeModification]
$removeOldDepartment.Add($oldValue) |Out-Null
$request.Modifications.Add($removeOldDepartment) |Out-Null
$result = $connection.SendRequest($request)

Powershell - passing variable into loop for string with quotes

I'm trying to understand how to setup my script so that single quotes will wrap around my variable. I have a list of 1500 customers I need to repeat my script for, so my thought as to do a foreach loop.
$customerlist = Invoke-Sqlcmd -Query "SELECT [CustomerNo] FROM [TABLE]" -ServerInstance "SERVER\INSTANCE"
#Loop through
foreach ($customer in $customerlist)
{
$inputParams = #{
"CustomerNo" = "'"+$customer+"'";
}
....Do rest of script
}
I need the $customer variable in my $inputparams to show with the string value in single quotes, e.g. '01233456' instead of just 0123456. I've tried several different iterations of "'"+$customer+"'" but cannot seem to get the correct syntax. Could someone help me out?
Invoke-Sqlcmd returns [System.Data.DataRow] type objects with the field name(s) and value(s) of your query result as its properties (basically a table). To select the value in the CustomerNo, you must specify the value by name:
# Expand the CustomerNo property to strings
foreach ($customer in $customerlist.CustomerNo) { }
# Or, later in the script:
$inputParams = #{
CustomerNo = "'$($customer.CustomerNo)'"
}

How to get creation date in sitecore with powershell

I wrote a script in order to replace the "$date" in release date of many Sitecore items with their creation date (created).
I have a problem to get this field from Sitecore.
I tried this:
$rootItem = Get-Item master:/content
$sourceTemplate = Get-Item "/sitecore/content/.../item 1"
foreach($field in $sourceTemplate.Fields) {
if (($field -ne $null) -And ($field -like '$date')) {
$sourceTemplate.Editing.BeginEdit()
$CreatedDate = .......
$field.Value = [sitecore.dateutil]::ToIsoDate($CreatedDate)
$sourceTemplate.Editing.EndEdit()
}
}
I also tried to get this field by ID but it doesn't work.
Does someone have an idea please?
Thank you
If you want to check Sitecore built-in fields, you need to call $sourceTemplate.Fields.ReadAll(); first.
You should compare value of the field with $date string, not the field itself.
Then just get the string which is stored in the __Created field instead of getting date and then formatting it back to ISO date string.
And the last thing - don't call Editing.BeginEdit() and Editing.EndEdit() mutliple times for the same item - Sitecore runs some havily operations when it's called so make sure you only call it once per every item which needs it.
$sourceTemplate = Get-Item "/sitecore/content/home/test"
$sourceTemplate.Fields.ReadAll();
$editing = $false
foreach($field in $sourceTemplate.Fields) {
if ($field.Value -eq '$date') {
if (!$editing) {
$editing = $true
$sourceTemplate.Editing.BeginEdit();
}
$field.Value = $sourceTemplate.Fields["__Created"].Value
}
}
if ($editing) {
$edited = $sourceTemplate.Editing.EndEdit();
}

Writing a hashtable value to an attribute

Powershell newbie here, my first script.
I have user objects with an AD custom attribute named tvCode with a values of 123456 or 6787682 or 983736 etc.
I would like to script something that will get the tvCode value from the user object
When:
123456 = Sony
6787682 = Samsung
9837343 = LG
Write the value of "Sony" or "Samsung" or "LG" to the "City" attribute of the user object.
Looks like i may need to use a hashtable.
If possible do this for a specific OU
hope this makes sense
thanks
function Convert-TVCode {
Param
(
[parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true)]
[String[]]
$Code
)
Process {
foreach ($C in $Code) {
switch ($C) {
"123456" {$brand = "Sony"}
"6787682" {$brand = "Samsung"}
"9837343" {$brand = "LG"}
default {
$brand = $null
Write-Warning "$C not included in switch statement. Returning"
return
}
}
if ($brand) {
Write-Verbose "Code '$C' matched to Brand '$brand' -- searching for users to update"
Get-ADUser -Filter "tvCode -eq '$C'" | Set-ADUser -Replace #{tvCode=$brand}
}
}
}
}
This function will allow you to update any users that have their tvCode attribute set as one of the target numerical values. You can have it hit multiple codes at once as well.
Examples:
Convert-TVCode -Code 123456
Convert-TVCode -Code 123456,6787682
Convert-TVCode -Code 123456,6787682,9837343 -Verbose
Update the switch statement in the function to customize it to your actual values and let me know if you have any questions!