0
votes

I am working on importing users into AD in bulk and have a script:

Import-Module ActiveDirectory
$path     = Split-Path -Parent $MyInvocation.MyCommand.Definition
$newpath  = $path + "\import_users.csv"
# Define variables
$log      = $path + "\created_ActiveDirectory_users.log"
$date     = Get-Date
$i        = 0

function createActiveDirectoryUsers {
  "Created the following Active Directory users (on " + $date + "): " | Out-File $log -Append
  "--------------------------------------------" | Out-File $log -Append

  Import-Csv $newpath | ForEach-Object { 
    $samAccount = $_.SamAccountName
    try {
      $exists = Get-ADUser -LDAPFilter "(sAMAccountName=$samAccount)"
    } catch { }
    if (!$exists) {
      $i++
      # Set all variables according to the table names in the Excel 
      # sheet / import CSV. The names can differ in every project, but 
      # if the names change, make sure to change it below as well.
      $setpass = ConvertTo-SecureString -AsPlainText $_.Password -Force
      New-ADUser -Name $_.DisplayName -SamAccountName $_.SamAccountName -GivenName $_.GivenName -Initials $_.Initials `
        -Surname $_.SN -DisplayName $_.DisplayName -Office $_.OfficeName `
        -Description $_.Description -EmailAddress $_.eMail `
        -StreetAddress $_.StreetAddress -City $_.L `
        -PostalCode $_.PostalCode -Country $_.CO -UserPrincipalName $_.UPN `
        -Company $_.Company -Department $_.Department -EmployeeID $_.ID `
        -OfficePhone $_.Phone -AccountPassword $setpass -Enabled $true -Path $_.OU

      $output  = $i.ToString() + ") Name: " + $_.CN + "  sAMAccountName: " 
      $output += $sam + "  Pass: " + $_.Password
      $output | Out-File $log -append
    } else {
      "SKIPPED - USER ALREADY EXISTS OR ERROR: " + $_.CN | Out-File $log -append
    }
  }
  "----------------------------------------" + "`n" | Out-File $log -append
}

createActiveDirectoryUsers

However when I try to import the CSV file, I am getting the following error:

New-ADUser : The object name has bad syntax
At C:\temp\bulk_create_users.ps1:33 char:17
+       New-ADUser <<<<  -Name $_.DisplayName -SamAccountName $_.SamAccountName -GivenName $_.GivenName -Initials $_.Initials `
    + CategoryInfo          : NotSpecified: (CN=Ranae Gentry...C=abbhq,DC=com":String) [New-ADUser], ADException
    + FullyQualifiedErrorId : The object name has bad syntax,Microsoft.ActiveDirectory.Management.Commands.NewADUser

Not exactly sure what syntax is wrong here.

2
@BenH Thanks! But I dont think thats the issue; for example if I remove the value for SamAccountName in the csv file, I get a normal error telling me that the value cannot be null.DangeRuss
What is the actual value of $_.DisplayName when the error occurs?Ansgar Wiechers
@AnsgarWiechers the value is the persons first and last name, no commas periods single or double quotes with a space between the first and last name. Example: Russ MittlerDangeRuss
Are there any rows with blank entries/values?Mathias R. Jessen
Sounds to me like you're original problem is solved :-) Do yourself a favor and add all the parameter arguments to a hashtable and then output the values before calling New-ADUser with Write-Debug or Write-Host in order to easier troubleshoot what might be going onMathias R. Jessen

2 Answers

0
votes

See if the following will help you out. I am not sure why you have $i++ during the creation of the user, but that actually is just counting down the CSV list. To me it is not very logical to add it in that location.

If the user does not exist, then create the user. ! = logical not Try to create the user first, but if the script has an issue please let me know with Catch.

You want the username to look logical inside of the OU of choice. We must rename the Idenity from the SAMaccount to the username.

The logging didn't look logical to me, and I have reworded it. Giving you the Full Name of the user, account name, and the password for easy reading any copy and past.

You can also use the following to see if the CSV file is outputting correctly.

#Test to make sure your output looks correct
#You can do this by running the following:
Import-csv ".\import_create_ad_users.csv" | Out-GridView



# ERROR REPORTING ALL
# When strict mode is on, Windows PowerShell generates a terminating error when the content of an expression, script, or script block violates basic best-practice coding rules.
    Set-StrictMode -Version latest

    Import-Module ActiveDirectory
$path     = Split-Path -Parent $MyInvocation.MyCommand.Definition
$newpath  = $path + "\import_users.csv"
# Define variables
$log      = $path + "\created_ActiveDirectory_users.log"
$date     = Get-Date
$i        = 0

Function createActiveDirectoryUsers {
  "Created the following Active Directory users (on " + $date + "): " | Out-File $log -Append
  "--------------------------------------------" | Out-File $log -Append
#Import CSV
  Import-Csv $newpath | ForEach-Object { 

# Check to see if SamAccount exists
$samAccount = $_.SamAccountName
    try {
      $exists = Get-ADUser -LDAPFilter "(sAMAccountName=$samAccount)"
    } catch { }
    If(!$exists){
     #Convert Password to Secure String
     $setpass = ConvertTo-SecureString -AsPlainText $_.Password -Force
          Try
          {

            New-ADUser  -Name $_.DisplayName -SamAccountName $_.SamAccountName -GivenName $_.GivenName -Initials $_.Initials `
            -Surname $_.SN -DisplayName $_.DisplayName -Office $_.OfficeName `
            -Description $_.Description -EmailAddress $_.eMail `
            -StreetAddress $_.StreetAddress -City $_.L `
            -PostalCode $_.PostalCode -Country $_.CO -UserPrincipalName $_.UPN `
            -Company $_.Company -Department $_.Department -EmployeeID $_.ID `
            -OfficePhone $_.Phone -AccountPassword $setpass -Enabled $true -Path $_.OU

            $dn = (Get-ADUser $_.SamAccountName).DistinguishedName

            # Rename the object to a good looking name
            $newdn = (Get-ADUser $_.SamAccountName).DistinguishedName
            Rename-ADObject -Identity $newdn -NewName ($_.GivenName + " " +  $_.Initials + " "+ $_.SN)


            #Create Log
            "[INFORMATION]`t Renamed the user $($_.SamAccountName) to $($_.GivenName) $($_.SN)`r`n" | Out-File $log -append
            "[INFORMATION]`t Created new user named: $($_.SamAccountName)" | Out-File $log -append
            "[INFORMATION]`t Password for new user: $($_.Password)" | Out-File $log -append

          }

          Catch
          {
           # Error if something with the user was broken
            Write-Host "[ERROR]`t Oops, something went wrong: $($_.Exception.Message)`r`n"
          }
        }
                Else
        {
          Write-Host "[SKIPPED]`t User $($_.SamAccountName) ($($_.GivenName) $($_.SN)) already exists or returned an error!`r`n"
          "[SKIPPED]`t User $($_.SamAccountName) ($($_.GivenName) $($_.SN)) already exists or returned an error!" | Out-File $log -append
    }
    $i++
  }
  "Processing ended (on " + $date + "): " | Out-File $log -append
  "--------------------------------------------" + "`r`n" | Out-File $log -append
}

createActiveDirectoryUsers

If the following script doesn't do what you want it to do, please leave a comment and I will fix it.

0
votes

What Mathias was suggesting is to put all your parameters and values in a hashtable:

$params = @{
    Name              = $_.DisplayName
    SamAccountName    = $_.SamAccountName
    GivenName         = $_.GivenName
    Initials          = $_.Initials
    Surname           = $_.SN
    DisplayName       = $_.DisplayName
    Office            = $_.OfficeName
    Description       = $_.Description
    EmailAddress      = $_.eMail
    StreetAddress     = $_.StreetAddress
    City              = $_.L
    PostalCode        = $_.PostalCode
    Country           = $_.CO
    UserPrincipalName = $_.UPN
    Company           = $_.Company
    Department        = $_.Department
    EmployeeID        = $_.ID
    OfficePhone       = $_.Phone
    AccountPassword   = $setpass
    Enabled           = $true
    Path              = $_.OU
}

so that you can output that hashtable for debugging purposes (to help identifying parameter issues), e.g. like this:

Write-Debug ([PSCustomObject]$params)

and splat it on New-ADUser:

New-ADUser @params

If you want output only in case an actual error occurred, you could put the New-ADUser statement in a try..catch statement, make all errors terminating errors, and output the current parameter data in the catch block after an error occurred.

try {
    New-ADUser @params -ErrorAction Stop
} catch {
    Write-Debug ([PSCustomObject]$params)  # output parameter info
    $_                                     # output the actual error
}