PowerShell Populate multi value attribute and convert case - powershell

I've tried to search but could not find anything whcih is not a surprise as I don't think what we're trying to do is so common.
I have a script that gathers a AD users according to filter together with custom attributes properties, we use a custom extended schema, and their values.
I do have an attribute called smtpHistory where an history of SMTP assigned to user are stored, I need to add what's in the $_.email attribute as the primary SMTP address (with SMTP in uppercase) while convertting any existing entry in lower case.
What I am doing right now is similar to
$mailHistory = $_.smtpHistory
$lowerMailHistory = $mailHistory.tolower()
# Insert all existing addresses in lowercase to the history attribute
Set-ADUser $_.SamAccountName -add #{ smtpHistory= $lowerMailHistory }
$newMail = $_.mail
# Append new default email address to smtpHistory
#Set-ADUser $_.SamAccountNAme -Add #{ smtpHistory= "SMTP:$newMail" }
Technically speaking the above works but when I check the smtpHistory attribute what I get is multiple values on a single line like
smtp:test7#gmail.com smtp:test6#gmail.com
Instead of one value per line like
smtp:test7#gmail.com
smtp:test6#gmail.com
The way I'm cycling through the users is via
$usersProxyAddress | ForEach-Object { ...
As using a foreach ($a in $usersProxyAddress ) is yielding the DN of each user and I cannot access the single properties (probably my fault).
Probably this is something silly that I'm overlooking but I cannot find a solution to the issue and any pointer/help would be highly appreciated.
Thanks in advance, Dan.

try something like this
$mailHistory = $_.smtpHistory -join ';'
$mHistory = $mailHistory -spilt ";"
foreach($mH in $mHisotry)
{
#yourcode
}
"Need to be tested as i dont have domain controller available with me now."

Related

Get AD user by providing fullName and manager full name

It might look silly but I'm struggling with finding user with Powershell by providing his full name and his manager full name. Purpose of script is to get SamAccountName and Email Address by using mentioned values which are provided by other team (these are the only unique values I get - getting user by Full Name is not any kind of problem, but it's possible that it'll return multiple results, and that's why Manager Full Name would determine appropriate result).
First I was using simple command
Get-ADUser -server $gc -Filter { (CN -eq $uFullName) -and (extensionAttribute4 -eq $mFullName) }
It worked great, but unfortunately I noticed that not all accounts use extensionAttribute4 to hold manager full name. I thought of using Filter on manager property but when I tried to use (Manager -like "*value*") it returned that like operator isn't supported by this attribute.
I'm still trying to find solution for this but maybe someone will have some solution to this situation.
Thank you in advance.

Powershell: Checking for duplicate email in AD

Background:
I'm trying to make a script that will see if a new users email ($email) is the same as one already existing (which would cause an error). I have a very remedial understanding of objects so this is what I have so far (yes it is ugly):
$email = "smithj#company.com"
$mailcheck = Get-ADUser -filter * -Properties * | ForEach-Object {$_.mail}
$mailcheck | ForEach-Object {if ($email -eq $_.mail){"$email = $($_.mail) - Matching email"}else{"$email = $($_.mail) - No duplicate email"}}
Problem 1:
The script doesn't match emails. When I have a matching email in AD it doesn't recognize it.
Problem 2: When executing just the 2nd line, indexing doesn't work properly. While it looks like a consecutive list of emails, if a user doesn't have an email at all (blank) really it could be something like this:
smithj#company.com
johnsonj#company.com
robertsr#company.com
doej#company.com
So $mailcheck[0] returns smithj#company.com while $mailcheck[1] returns blank despite the list actually looking like this:
smithj#company.com
johnsonj#company.com
robertsr#company.com
doej#company.com
Conclusion: I really just need problem 1 solved but problem 2 peaked my curiosity. Thanks.
The way you are doing it above is really inefficient. -Properties * will return every property on the user, some properties are expensive in terms of processing power to return. Only use the properties you need. The properties returned by default without specifying that parameters do not need to be specified with -Properties, only additional nondefault properties. -Filter * will also match on literally any value for any field, effectively returning every ADUser, further increasing the resources required for your script to execute as you will now have to process every user to find any accounts matching that email.
Now that that's out of the way, here is a more efficient method to implement what you're asking:
# Set the email address to search for
$emailAddress = 'box#domain.tld'
# Get all users where the email address matches what is set above
# Force it as an array so you can treat it like one even if only
# one or zero users are returned
$adUsers = #( Get-ADUser -Filter "EmailAddress -eq '${emailAddress}'" )
# Make sure no accounts were returned
# If there are, throw an error with the number of users and who they are
if( $adUsers ) {
throw "Found $($adUsers.Count) users matching EmailAddress ${emailAddress}: $($adUsers.SamAccountName -join ', ')"
}
By using the filter to only match the specific email address, Powershell does not need to collect every single AD user in the system, or iterate over all of them to find a specific email address. This will take a long time to check, especially in larger environments, whereas filtering the returned objects based on email address (or on any other property) results in a faster operation and less data to sift through.
You can then check whether $adUsers contains anything (an array count of anything but 0 evaluates to $True, you could also use if( $adUsers.Count -gt 0 ) as the condition), and if so, throw an error with more information as I do above.
Update for comment question:
To answer your other question in the comment, "I didn't know what object to compare $email to", EmailAddress and Mail both look to be valid properties, but I don't know the difference between them. In my environment, both Mail and EmailAddress are populated with my email address, but have always used EmailAddress and haven't run into issues using that. Maybe one is deprecated and the other is new or something, but I'm not really sure.
There is also yet another property called proxyAddresses as well, which preliminary research shows that both EmailAddress and Mail are related to it, but I don't know much about it. It's not populated on my ADUser objects, so I can't poke around with it.

How do I use Set-ADuser with the -Instance parameter to update an attribute to blank?

We've been using Powershell to bulk update our AD for several years with data from a CSV file. The code is pretty straight forward:
$Empinfo = Import-CSV AFile.csv
$EmpAD = Get-Aduser someone
$EmpAD.Title = $EmpInfo.Title
$EmpAD.streetAddress = $Empifo.street
$EmpAD.PostalCode = $Empifo.zip
<snip>
Set-ADUser -Instance $EmpAD
Recently, the street and zip info have been blanked for some people due to organizational weirdness. When we run the same script and try to set, say streetAdress to nothing, Set-ADuser throws a "replace" error.
(Note that I tried setting streetaddress to a single space and it still failed.)
After much trial and error, today I was able to make it work by testing for blankness and using the following:
if (Empinfo.street -eq $null) {
Set-ADUser $EmpAD -Clear streetaddress,postalCode
} else {
$EmpAD.streetAddress = $Locations[$site].street
$EmpAD.PostalCode = $Locations[$site].zip
}
In other words, we have to issue a specific -Clear action to accomplish this.
Is this how we should expect this to work? I cannot see anything in the -Instance parameter docs that says you cannot empty an attribute in the manner we were trying.
Yes , you have to use -Clear like how you have already done in the sample code in order to accomplish this. Thats the correct way to do that.
Empty field is actually holding the attribute value as Null.
So clearing that is important.

LDAP userAccountControl atttribute

In PowerShell I use the following LDAP query to retrieve the active directory properties of a host name:
$Filter = "(&(ObjectCategory=Computer)(ObjectClass=Computer)(CN=$ComputerName))"
if ($Found = ([ADSISEARCHER]$Filter).FindOne()) {
$Details = $Found.GetDirectoryEntry()
}
Once I have these properties I would like to check if the computer account is disabled. The following LDAP query is allowing me to do that:
$Filter = "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=2)(CN=$ComputerName))"
([ADSISEARCHER]$Filter).FindOne()
What I would like to know is, how can I avoid using the second LDAP query and use the variable $Details from the first LDAP query to obtain $True or $False if the computer account is disabled?
I found some extra information but I can't seem to put the pieces together.
Thank you for your help.
The information you're looking for is encoded in the userAccountControl of the directory entry object. However, the property contains an array with a numeric value, so you need to check if the "disabled" flag (numeric value 2) in the first array element is set:
$disabled = [bool]($Details.userAccountControl[0] -band 2)

Find and replace custom attribute values in AD using Powershell

So I have an interesting script I am trying to figure out, basically I need to change a custom attribute value to a new one. The problem is its for both users and computers and not specific to the groups. So for instance the value might be Billing1 for several users in an OU and this need to be Billing2. So I need to find any instance of the Value of Billing1 and change it to Billing2 not knowing the user or computer object. I can successfully change one at a time if I know who the user is by using Set-ADUser, Set-ADComputer and even with Set-AdObject but I need to figure out a Find and replace function.
I have searched for this and I have found examples of where I can use CSV for users and computers but again I don't know who has what since the value in the attribute can vary and also changes if a reorg happens.
got the correct script...
Get-ADComputer -Properties enterattributename -Filter {enterattributename -like "value to search" } |Set-ADComputer –replace #{ enterattributename =”value to change”}
this also can be applied to Get-ADUser and Get-ADObject