Problems creating account in AD with Powershell, data from SQL
Hello Experts,
I have a scenario where I have data in SQL & I'm using powershell to look into SQL in a particular column "Action",
1. if the value is create, then it should create account in AD, this should be for all the entries.
2. if the value is update, then it should do something else (my aim is to do set-aduser for existing users)
3. After any of the activities is done, it should set the value of the column for all these entries to Blank or NULL.
Currently it fails to create the account, except for only 1.
It also doesn't set the value to Blank.
Can someone please help?
Regards,
A
Import-Module ActiveDirectory# Path to create users in$path = "OU=TestUser,OU=Test,DC=Test,DC=com"# Connection string to SQL Server database$connectionString = "Server=WIN8\SQLEXPRESS;Database=DBA_Utilities;Trusted_Connection=yes;"# Select statement to return new user accounts# Needs to return "sAMAccountName" & "Password" columns# Note: Other columns names should match AD attribute name$sql = "Select FirstName as GivenName, LastName as sn, DisplayName as DisplayName, samAccountName as sAMAccountName, EmailAddress as mail, City as l, Department as Department, StreetAddress as StreetAddress, State as st, samAccountName+'@wuestundpartner.com' as userPrincipalName, PostalCode as postalcode, MobilePhone as mobile, OfficePhone as telephoneNumber, Department as department, Title as Title, Office as physicalDeliveryOfficeName, c as c, CountryCode as co, Action as Action, 'Abc-123456' as Passwordfrom GetActiveDirectoryUsers where Action = 'update' OR Action = 'create' "###########################$cn = new-object system.data.sqlclient.sqlconnection$cn.ConnectionString = $connectionString$cn.Open()$cmd = New-Object System.Data.SqlClient.SqlCommand$cmd.CommandText = $sql$cmd.connection = $cn$dr = $cmd.ExecuteReader()$colCount = $dr.FieldCount$sAMAccountNameOrdinal = $dr.GetOrdinal("sAMAccountName")$PasswordOrdinal = $dr.GetOrdinal("Password")$DisplayNameOrdinal = $dr.GetOrdinal("DisplayName")$ActionOrdinal = $dr.GetOrdinal("Action")while ($dr.Read()){ # Get value of sAMAccountName column $sAMAccountName = $dr.GetValue($sAMAccountNameOrdinal) # Get value password column (converted to secure string for New-ADUser Cmdlet) $password = ConvertTo-SecureString -AsPlainText $dr.GetValue($PasswordOrdinal) -Force # Get value of DisplayName column $DisplayName = $dr.GetValue($DisplayNameOrdinal) $Action = $dr.GetValue($ActionOrdinal) #write-host "Creating user account..." $sAMAccountName $otherAttributes = New-Object System.Collections.HashTable # Create a hash table of attribute names and attribute values # Used to populate other attributes. for ($i = 0; $i -le $colCount - 1; $i++) { $attribute = $dr.GetName($i) switch ($attribute) { "Password"{ } #Ignore "SAMAccountName" { } #Ignore "Action" { } #Ignore default { $otherAttributes.Add($attribute, $dr.GetValue($i)) } } } # Capture Error for not resetting SQL Values in Action $Error.clear() # Create Active Directory User Account if ($Action -eq 'create') { try { Write-Host "Create branch executed for $sAMAccountName" New-ADUser -sAMAccountName $sAMAccountName -Name $DisplayName -Path $path -otherAttributes $otherAttributes -Enable $true -AccountPassword $password -PasswordNeverExpires $true #Write-Host "UserID $($DisplayName) created!" } catch { Write-Host "There was a problem creating UserID $($DisplayName). The account was not created!" Write-Host "Error message: $($_.Exception.Message)" } } elseif ($Action -eq 'update') { Write-Host "Update is triggered for $sAMAccountName" }}$dr.Close()# If the code runs successfully, then Clear the value from SQL in Actionif (!$Error){ $updateqry = "update dbo.GetActiveDirectoryUsers set Action = ' ' where Action = 'Yes';" $cmd.CommandText = $updateqry $cmd.ExecuteNonQuery()}$cn.Close()
Thanks Chris,
That seemed to work!
I have to check other issues, but have to run out.... sorry
Will update later.
Thanks,
A
Ackles
ASKER
Just a quick one, out of the three accounts, 2 were created & 1 got error: Server is unwilling to process the request?
Chris Dent
That would suggest one of the attribute values you're pushing is invalid. For example, if you were trying to push a blank attribute that might happen. If this hypothesis is true, you can counter it by changing this line:
Note: We have $null on the left hand side of the expression above to properly handle array values. And we don't use implicit boolean ("if ($value)") because 0 and $false are legitimate values in some cases.
first of all I am not a powershell scriptor but I think you can do it through try and catch command
Import-Module ActiveDirectory# Path to create users in$path = "OU=TestUser,OU=Test,DC=Test,DC=com";# Connection string to SQL Server database$connectionString = "Server=WIN8\SQLEXPRESS;Database=DBA_Utilities;Trusted_Connection=yes;"$sql = "Select FirstName as GivenName, LastName as sn, DisplayName as DisplayName, samAccountName as sAMAccountName, EmailAddress as mail, City as l, Department as Department, StreetAddress as StreetAddress, State as st, samAccountName+'@wuestundpartner.com' as userPrincipalName, PostalCode as postalcode, MobilePhone as mobile, OfficePhone as telephoneNumber, Department as department, Title as Title, Office as physicalDeliveryOfficeName, c as c, CountryCode as co, Action as Action, 'Abc-123456' as Password| Foreach-Object {try {$x = get-aduser "$($_.Old)"; $OldExists = $TRUE;} catch { $OldExists = $FALSE; }#try {$x = get-adgroup "$($_.New)"; $NewExists = $TRUE;} catch { $NewExists = $FALSE; }If ($OldExists -eq $TRUE ) { Set-ADUser -Name $_.New -Path $path -PassThru } else { Write-Host "User already Exist" } |New-ADuser -Name sAMAccountName -Path $path -PassThru}
You could, but using exception handling to create what amounts to an if statement is a bad practice.
For example, in this case, if something goes wrong with the first of your commands (Get-ADUser) for some other reason (like a syntax error), you immediately flag the account for creation. This is not a good test at all.
You'll have to drop all the attributes out to see exactly what you're pushing in. If there are any obvious problems those can be handled, One thing we didn't test for above is DBNULL. I seem to remember that doesn't present quite as cleanly to PowerShell as the test we've used above.
Ackles
ASKER
Thanks Tahir,
Chris, I would like to resolve the issue with the existing script.
I have checked both the created & faulty accounts, they have exactly the same values.
Any thoughts?
Ackles
ASKER
Chris,
So you are saying that I only leave the Name attribute & delete all the rest?
Is there a way,
if value is empty, ignore & don't throw error....
Chris Dent
Not with the AD commands, we need to stop it getting added to the set in the first place. That's what the if statement above is attempting to do. We just need to tweak it to squash the DBNULL values. I've had this problem pulling from SQL (and pushing into AD) before.
Ackles
ASKER
Sorry about delay, so I put extra quotes but the problem persists....
Are any of those fields different for the account that works properly? The only thing that stands out is the trailing white space on the co field (that one again :)).
I have exactly same values in the fields where it work :(
Ackles
ASKER
when I removed the values to check, I never removed co, it was there & this account was made?
Chris Dent
Oh hold on, is this throwing an error when calling New-ADUser because the account already exists? I thought you were deleting the account and testing again, perhaps I misunderstood?
Set-ADUser and try each one in turn. I don't have a domain I can play with, I can't do it for you I'm afraid.
If it works without passing attributes, the attribute set is to blame. If none are obviously wrong it's something slightly more arcane. Obvious choices are values on constrained attributes (like userPrincipalName), but it could be something less obvious still.
Chris Dent
Do bear in mind that this process of elimination should result in a permanent fix within the script. It's a one-time effort.
Chris,
As i mentioned earlier,
4 Attributes:
Office as physicalDeliveryOfficeName,
MobilePhone as mobile,
OfficePhone as telephoneNumber,
Title as Title,
Problem is that I need these to be filled, when I remove them then script works, even if I fill them it still fails
In the two values it doesn't work, its Empty
Out of the 2 it works, it's also Empty in 1 ...
So I don't understand why it fails & why it works....
Chris Dent
Is it really empty though? There's a difference between ' ' and ''. In theory if it were empty the trap we added to avoid pushing empty attributes should have prevented it going ahead.
That seemed to work!
I have to check other issues, but have to run out.... sorry
Will update later.
Thanks,
A