AD user creation with SamAccountName availability check loop - powershell

I'm learning Powershell by making a script that will hopefully automate everything that needs to be done when we get a new hire or a consultant. Currently I'm working on the part that will create the AD account. Below are the variables specific to this portion of the script.
#Variables for preliminary SamAccountName, modifiers and initials array
$PrelSamAccountName = ("se" + [string]$GivenName.Substring(0,3) + [string]$SurName.Substring(0,3)).ToLower()
$Modifier1 = 1
$Modifier2 = 0
$InitialsArray = #("x","y","z")
Here is the loop. I cut out a bunch of parameters on New-ADUser to make it less cluttered.
try {
#Checks if preliminary SamAccountName is taken or not
$ADCheck = Get-ADUser -Filter {SamAccountName -eq $PrelSamAccountName}
#Creates new user
New-ADUser -Name $Name -SamAccountName $PrelSamAccountName
} catch {
#Replaces final character in preliminary SamAccountName with "1++"
while (($ADCheck | Select-Object -ExpandProperty SamAccountName) -eq $PrelSamAccountName) {
$PrelSamAccountName = ([string]$PrelSamAccountName.Substring(0,7) + ($Modifier1++)).ToLower()
}
#Changes $Initials from $null to x/y/z if an existing user has identical name as new user
while (($ADCheck | Select-Object -ExpandProperty Name) -eq $Name) {
$Initials = $InitialsArray[$Modifier2++]
$Name = $GivenName + " " + $Initials + " " + $SurName
}
}
Everything is working as intended, except for the fact that a new user is created every other time I run the loop. Ideally I would want it to create a new user every time it is run. :)
I'm assuming it has something to do with the placement of the $ADCheck variable, but after having rewritten this portion multiple times I simply can't get it to work. Any ideas?
Thanks in advance.

You have some logical problems in here:
Follow this Approach:
Pseudocode:
while (user exist) {create new username}
new-aduser new username
PS Code:
function new-sam
{
#creates new sam
}
$sam = "username"
$a=$false
while (!$a)
{
try {
$a = [bool](Get-ADUser -Identity $sam )
}
catch {
$a = $false; $sam = new-sam
}
}
new-aduser ....

Related

how to concatenate multiple address in powershell

I have a list of users but I don't know each user email domain so I'm just wondering how can I concatenate all the domains from $alldomans at the end of their name one by one and try to find their employeeId.
For example, I'm doing like this right now and this is working but I'll have more than one email domain so I'm just wondering how can I pass the domain from my list one by one and try to find their employee Id?.
$EmployeeId= $policy.name | foreach { (Get-AzureADUser -ObjectId "$($_)#gmail.com").ExtensionProperty.employeeId}
I've tried it like this but still not working for some reason
$allDomains = #(
"gmail.com",
"yahoo.com",
"outlook.com"
"hotmail.com"
)
$EmployeeId= $policy.name | foreach { (Get-AzureADUser -ObjectId "$($_)#$allDomains").ExtensionProperty.employeeId}
You need an inner loop for the Domains:
$allDomains = #(
"gmail.com",
"yahoo.com",
"outlook.com"
"hotmail.com"
)
$EmployeeId = $policy.name | ForEach-Object {
foreach($domain in $allDomains) {
try {
$azUsr = Get-AzureADUser -ObjectId "$_#$domain" -ErrorAction Stop
# using `return` here so that if `$azUsr` could be found,
# we stop this inner loop and go to the next user
return $azUsr.ExtensionProperty.employeeId
}
catch {
Write-Warning $_.Exception.Message
}
}
}

Creating New Contacts In Bulk AND adding to distros

I have a script that creates bulk external contacts using PS and a CSV. I would like to tweak this to not only create the contact but also add the contact to any specified distros.
foreach($contact in (import-csv c:\users\ME\desktop\contactstest.csv)){
$properties = #{
type = 'Contact'
name = $contact.firstname + ", " + $contact.lastname
OtherAttributes = #{'mail' = "$($contact.email)"}
Path = "OU=External Contacts,DC=Company,DC=org"
}
New-ADObject #properties
}
If I have the CSV with the following columns. Is this do-able?
Firstname/lastname/email/Group
The CSV is located on the desktop of the DC.
CSV EXAMPLE
first,last,email,group
billy,bob,bb#aol.com,emailist1
I see now what went wrong the first time.
What I meant was for you to replace the line New-ADObject #properties with my code block. Since you left that in aswell, the code tried to create the contact twice, leading to the error message and skipping the part where it add the contact to the group(s).
If your CSV looks like this:
first,last,email,group
billy,bob,bb#aol.com,emailist1
jane,doe,jd#somewhereintheworld.com,emaillist1;emaillist5
Note the second contact is to be added to two groups, separated by a semi-colon ;
Here the code in full:
foreach ($contact in (import-csv c:\users\ME\desktop\contactstest.csv)) {
# create a hash table for splatting the parameters to New-ADObject
$properties = #{
type = 'Contact'
name = $contact.firstname + ", " + $contact.lastname
OtherAttributes = #{'mail' = "$($contact.email)"}
Path = "OU=External Contacts,DC=Company,DC=org"
}
# create the contact and capture the resulting object
$newContact = New-ADObject #properties -PassThru -ErrorAction SilentlyContinue
if ($newContact) {
# if success, add this contact to the group(s)
$contact.Group -split ';' | ForEach-Object {
Add-ADGroupMember -Identity $_ -Members $newContact
}
}
else {
Write-Warning "Could not create contact $($contact.lastname)"
}
}
P.S. You can also include the PassThru and ErrorAction parameters to the splatting hash:
$properties = #{
type = 'Contact'
name = $contact.firstname + ", " + $contact.lastname
OtherAttributes = #{'mail' = "$($contact.email)"}
Path = "OU=External Contacts,DC=Company,DC=org"
PassThru = $true
ErrorAction = 'SilentlyContinue'
}

handle ADIdentityNotFoundException without stopping the program

I have to loop for each object in an input file, doing a Get-ADUser on each object, and I want to handle the ADIdentityNotFoundException error without stopping the loop. Is there a better way I can accomplish this (simplified for example's sake):
Import-Csv $input | Foreach-Object {
$manager = "BLANK"
if ($user = Get-ADUser $_."samaccountname" -properties * ) {
# I don't think I need this in an IF{} since the line below won't work
# so $manager will be equal to the last value set, "BLANK", but
# this makes it easier to understand what I want to happen
$manager = $user."manager"
# I need more properties (thus -properties *) but again just an example
}
}
In essence, if the Get-ADUser lookup is successful, set $manager = $user."manager"
If it is not successful, do not stop the loop, do not copy the value of the previous user, have $manager = "BLANK"(or whatever). The issue I have with the try/catch solutions, is that ADIdentityNotFoundException doesn't trigger the catch unless I add -ErrorAction Stop, which will cause the undesired result of the program terminating.
I'm not sure why your program would be terminating. Using the below sample code loops through all the users in the array. I have purposely entered an incorrect username into the second value of the array (position [1]):
$users = "username1", "username2", "username3" #username2 is purposely incorrect
foreach ($i in $users){
try{
$user = Get-ADUser -Identity $i -Properties * -ErrorAction Stop
Write-Host "Found"
}catch{
Write-Host "Not found"
}
}
my output is
found
not found
found

Capture multiple variables

I currently have a powershell script that allows me to enter in the details for users one at a time which can then be used as variables later on. At present the script calls for each input and then saves for as a variable, this is then repeated 10 times.
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
$NameOne = [Microsoft.VisualBasic.Interaction]::InputBox("Enter UserName")
$firstname,$surname = $NameOne -split("\.")
$NameTwo = [Microsoft.VisualBasic.Interaction]::InputBox("Enter UserName")
$firstname,$surname = $NameTwo -split("\.")
Is there a way to shorten the script to both allow usernames to be input and stored but to also move on to the next part of the script when an InputBox has no data input?
Thanks
Tom
Use a while loop:
$Users = while(($Username = [Microsoft.VisualBasic.Interaction]::InputBox("Enter UserName")).Trim() -ne "")
{
$firstname,$surname = $Username -split '\.'
New-Object psobject -Property #{
Firstname = $firstname
Surname = $surname
Username = $Username
}
}
When the user inputs nothing or whitespace, the loop will exit, otherwise it'll create a new "User object" that will end up in the $Users array

How can I optimize my PowerShell - LDAP Query?

I have created a script that reads from a CSV (or other dataset, but not posting that side) and creates users in my AD environment.
Basically, whatever dataset is passed into the script will be processed, and then a user will be created if they do not exist. If the user exists in the AD already, then the script skips over the entry. This is a CREATE only script.
It's pretty slow, and I'd like to improve the performance whilst keeping the functionality. Can you give me any tips as to how I can make this perform better?
import-csv "c:\PSScripts\LDAP\ADMigrate.csv" | ForEach-Object {
# Define the User OU
$usersOU = [ADSI] "LDAP://ou=Students, dc=live,dc=tcicollege,dc=edu"
# Check for existing users
$existingUsers = ($usersOU.psbase.children | Where-Object {$_.psBase.schemaClassName -eq "User"} | Select-Object -expand Name)
$userQuery = $existingUsers -contains $_.'AccountName'
if ($userQuery) {
echo $_.'AccountName' " already exists in Directory."
} else {
# Create a new user
$newUser = $usersOU.create("user","cn=" + $_.'AccountName')
# Set Account AttributesAMAccountName
$newUser.Put("sAMAccountName", $_.'AccountName')
$newUser.Put("givenName", $_.'FirstName')
$newUser.Put("employeeID", $_.'StudentID')
$newUser.Put("sn", $_.'LastName')
$newUser.Put("department", $_.'Department')
$newUser.Put("company", $_.'SyStudentID')
$newUser.Put("UserPrincipalName", $_.'AccountName' + "#live.tcicollege.edu")
$newUser.Put("mail", $_.'AccountName' + "#live.tcicollege.edu")
$newUser.Put("displayName", $_.'LastName' + "," + " " + $_.'FirstName')
# First Commit
$newUser.SetInfo()
$newUser.userAccountControl="66048"
$newUser.Put("pwdLastset", -1)
$newUser.SetPassword($_.'Password')
# Final Commit
$newUser.SetInfo()
echo $_.'AccountName' " created successfully."
}
}
Thank you in advance for any help you can offer.
Try the static Exists() method to find if the user exists in the Students OU:
$user = [ADSI]::Exists("LDAP://cn=$($_.AccountName),ou=Students, dc=live,dc=tcicollege,dc=edu")
if(!$user)
{
"create code goes here"
}
The $usersOU value is static so you can take it out, place it before the import-csv command.