Hello Everyone,
I am writting some PowerShell Modules for importing AD accounts from a CSV. Below is the code:
Function Import-ADUsers {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true,HelpMessage='Supply the CSV file name and path')]
[String]$CSVFile)
$users = import-csv $CSVFile
foreach ($user in $users) {
$pass = ConvertTo-SecureString -AsPlainText $user.AccountPassword -force
#define a hashtable to splat to New-ADUser
$hash = [ordered]@{
Description = $($user.description);
Employeeid = $($user.employeeID);
Path = $($user.distinguishedName);
givenname = $($user.givenname);
surname = $($user.sn);
name = $($user.name);
emailaddress = $($user.mail);
title = $($user.title);
department = $($user.department);
streetaddress = $($user.streetaddress);
city = $($user.l);
postalcode = $($user.postalcode);
officephone = $($user.telephonenumber);
mobilephone = $($user.mobile);
sAMAccountName = $($user.samaccountname);
office = $($user.physicalDeliveryOfficeName);
accountpassword = $pass;
otherattributes = @{extensionattribute1=($user.extensionattribute1);proxyaddresses=($user.proxyaddresses -split ';')}; #this splits the proxyaddress string from the CSV, using ; as a delimiter
#otherAttributes = @{proxyAddresses = ("SMTP:" + $user.mail)};
userprincipalname = $($user.mail);
} #close hash & child hash
Write-Debug "Preparing to query $computer"
New-ADUser @hash -Enabled $true -ChangePasswordAtLogon $true -PassThru -Server hhs-ln1-pdc01
} #close foreach
} #close function
Function Enable-MEU {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,
HelpMessage='Supply the CSV file name and path')]
[string]$CSVfile,
[Parameter(Mandatory=$True,
HelpMessage='Supply the target address starting with @')]
[string]$TargetAddressSuffix
)
# Connects to Exchange Server Remotely
#Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File C:\scripts\EXpassword.txt
$password=get-content C:\scripts\EXpassword.txt | ConvertTo-SecureString
$userid='a01.stuart.hendry'
$UserCredential=New-Object System.Management.Automation.PSCredential $userid,$password
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://hhs-ln1-pexc01/PowerShell/ -Authentication Kerberos -Credential $UserCredential
Import-PSSession $Session
$users = import-csv $csvfile
$targetaddresssuffix = $targetaddresssuffix
foreach ($user in $users) {
Enable-MailUser $user.SamAccountName -ExternalEmailAddress ($user.samaccountname + $targetaddresssuffix)
#New-MailUser $user.SamAccountName -ExternalEmailAddress $users.emailaddress
#Set-MailUser $user.SamAccountName -EmailAddresses @{Add="$user.samaccountname",$targetaddresssuffix}
} #close foreach
} #close function
I want a way to check each hash table value, and if its $null (blank) then take it out of the hash table. The reason is, New-ADuser errors when some values in the HASH table are blank. For example, the ‘description’ field in the CSV import is blank. So the HASH table imports from the CSV it then passes a blank value to New-ADUser. This then causes an error. So I want a way to run an IF statement within the HASH table to check if the attribute has an assigned value. SO if = $null then dont pass the parameter to New-ADUser.
Is it ok to do IF / ELSE statements from within the hash table? Or is there a better way?
Many Thanks
The best approach will be to wrap New-ADUser in a Try Catch block and handle the errors. When you catch an error you could write it to a log file so you know which ones failed.
You can remove the keys with null values, but you have to take care. You can’t remove items while iterating through them. Create a list of the items to remove, then remove them.
Untested
$rem = New-Object System.Collections.ArrayList
foreach ($h in $hash.Keys) {
if ([string]::IsNullOrEmpty($($hash.Item($h)))) {
[void]$rem.Add($h)
}
}
foreach ($h in $rem)
{
$hash.Remove($h)
}
Another option is to add items to the hashtable if it’s not null:
Function Import-ADUsers {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true,HelpMessage='Supply the CSV file name and path')]
[String]$CSVFile
)
$users = import-csv $CSVFile
foreach ($user in $users) {
$pass = ConvertTo-SecureString -AsPlainText $user.AccountPassword -force
#define a hashtable to splat to New-ADUser
$hash = [ordered]@{
Description = $($user.description);
Employeeid = $($user.employeeID);
Path = $($user.distinguishedName);
givenname = $($user.givenname);
surname = $($user.sn);
name = $($user.name);
emailaddress = $($user.mail);
title = $($user.title);
department = $($user.department);
streetaddress = $($user.streetaddress);
city = $($user.l);
postalcode = $($user.postalcode);
officephone = $($user.telephonenumber);
sAMAccountName = $($user.samaccountname);
office = $($user.physicalDeliveryOfficeName);
accountpassword = $pass;
otherattributes = @{extensionattribute1=($user.extensionattribute1);proxyaddresses=($user.proxyaddresses -split ';')}; #this splits the proxyaddress string from the CSV, using ; as a delimiter
#otherAttributes = @{proxyAddresses = ("SMTP:" + $user.mail)};
userprincipalname = $($user.mail);
Enabled = $true
ChangePasswordAtLogon = $true
Server = "pdc01"
PassThru = $true
} #close hash & child hash
#if the mobile is not null, add it to the hash
if ( $user.mobile ) {$hash.Add( "mobilephone", $($user.mobile)) }
Write-Debug "Preparing to query $computer"
New-ADUser @hash
} #close foreach
} #close function
Hi, thanks, yes I want to add in error reporting too at a later point, and was going to use the TRY CATCH method. However in many cases, its ok if these fields are blank. Could be that some fields like description are not desirable so would be left out on purpose, but this shouldnt be parsed otherwise it will error, rather it should be removed if blank. Then if critial attributes are missed (perhaps SamAccountName) then at that point it should be logged as a fail error and carry on with the rest.
Not quite there let with the error reporting bit, but its on the list of things. Takes me ages, as I am still learning. Thanks for your suggestion
Awesome, looks good, I’ll try this now, thank you
Hi Rob,
I am just testing this out in a more simplied form. Cant see to get it to work:
$users = import-csv c:\import1.csv
foreach ($user in $users) {
#if the mobile is not null, add it to the hash
if ( $user.Description ) {$hash.Add("Description", $($user.description)) }
}
Just says “You cannot call a method on a null-valued expression.” I have turned on Debug mode in ISE, and its getting stuck on the IF statement. I have checked all the variables using Debug, $user is popupated with a ‘description’ within it.
I expect its a very simple fix. I went on an advanced course recently, but the devil is in the detail. As a beginner its always catching me out.
Thanks
Tried this too:
$users = import-csv c:\import1.csv
foreach ($user in $users) {
$hash = [ordered]@{
Description = if ( $user.Description ) {$hash.Add("Description", $($user.description)) };
}
}
This almost works, but the output of $hash is:
Name Value
Description
So the value is blank
oh ive figured it out now thanks
if ( $user.description ) {$hash.Add( "description", $($user.description)) };
if ( $user.sn ) {$hash.Add( "surname", $($user.sn)) };
I thought you needed the ‘@’ to start a hash table. So your solution is to do away with the hash table, and create an array with $hash
Seems to work, is my understanding correct?
Thanks
Stuck at this point now:
if ($_.Description) {$hash.Add("Description", ($_.description)) };
Seems pipeline variables are not compatible in the syntax above. How to I use $_.var within the $hash.add ?
Many Thanks
Try this:
$hash.Add(“Description”, ($_).description)
perfect, may I ask, why is it necessary to put the ‘$_’ into brackers just because its a pipeline var?
I don’t know the exact technical reason, it has something to do with the order of evaluation inside of the function call.
This specific error is because you’ve not defined $hash in your code. After your import-csv and before the foreach, just add $hash=@{} and this code should work.
With the least modification of your original code in mind, you can simply remove empty values by doing this:
Foreach($val in $hash.keys){
If([string]::IsNullOrEmpty($hash[$val])){
$hash.remove($val)
}
}
Place that before you call new-aduser.