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

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

Related

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)'"
}

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!

Convert data type of property for all objects in an array

Say I have an array of objects:
$a = #(
#{ Name = "A"; Value = "2016-01-02" },
#{ Name = "B"; Value = "2016-01-03" },
#{ Name = "C"; Value = "2016-01-04" }
)
The Value property is currently a String. I want to convert the Value property of each object to a DateTime. I could accomplish this with a for loop, but I was wondering if there is a more direct way to do it.
Yes, calculated properties.
$a | select #{N='Name';E={$_.Name}}, #{N='Value';E={ [datetime]$_.Value }}
This will change data type of the first object Value to datetime.
$a[0].value = [datetime]::ParseExact($a[0].value,'yyyy-MM-dd',$null)
And the loop from here :
foreach ($Obj in $a)
{
$Obj.Value = [datetime]::ParseExact($Obj.value,'yyyy-MM-dd',$null)
}
The #TessellatingHeckler 's answer, which you accepted, is not correct for your question! It is only change the representation of the data in the object, but not converted it as you ask. Even if you save it as a new object (or overwrite the original) this will change the object itself. You can see the difference if you run flowing code:
$b=$a | select #{N='Name';E={$_.Name}}, #{N='Value';E={ [datetime]$_.Value }}
#check the original and converted object
$a|gm
$b|gm

Modify value when getting value of key from a hashtable in PowerShell

In PowerShell, I have a structure (HashTable type) created like so:
$Structure = #{
"KeyOne" = "Value"
"KeyTwo" = "{Change.This.That}"
"KeyThree" = "{Change.This.Thing} With Stuff"
"Change" = #{
"This" = #{
"That" = "Another Value"
"Thing" = "Yogurt"
}
}
}
The string with the curly brackets are placeholders/tokens for what the actual value should really be, stored in a string format as a reference to the dot notation of some other value within the same object.
I wrote a function to take that tokenized value and retrieve what the actual value is supposed to be that works perfectly fine. Only problem is I have to execute the function every time there is a tokenized value. Is there anyway I can simplify this, specifically instead of running:
#I pass structure because I'd rather avoid assuming
#the hashtable will always be called $Structure
Convert-Token -String $Structure.KeyTwo -Obj $Structure #Another Value
is there anyway I can automatically do this by just pulling the bracket notation?
#Like this?
$Value = $Structure["KeyThree"]
$Value #Yogurt With Stuff
Possible? Not possible?
You can probably do something like this:
$Selector = $Structure
$Structure = #{
"KeyOne" = "Value"
"KeyTwo" = "$($Selector.Change.This.That)"
"KeyThree" = "$($Selector.Change.This.Thing) with Stuff"
"Change" = #{
"This" = #{
"That" = "Another Value"
"Thing" = "Yogurt"
}
}
}
$Structure["KeyThree"]