Share via

Adding New-ADUser(s) from CSV file using pipeline

Brian Mallett 21 Reputation points
2021-05-19T17:21:55.807+00:00

I am trying to import a CSV export from one system and import into AD. I have a series of things to handle, but essentially, I just need to create the OU's and Groups if they don't exist (To build out the framework/structure of the environment). Then run through and check for users, adding them if they aren't there. Ideally I would update the users if they were already in AD.

Here is the script thus far. Everything looks ok when I dump it using Out-GridView. This is what it looks like using Out-Default:

Name                  : 11506
SamAccountName        : 11506
DisplayName           : Jon Aber
GivenName             : Jon
Surname               : Aber
MiddleInitial         : T
EmailAddress          : ******@student.devdc.com
Description           : 11506
Path                  : OU=11,OU=705,OU=Students,DC=DEVDC,DC=COM
PasswordNeverExpires  : True
Enabled               : True
ChangePasswordAtLogon : False
AccountPassword       : System.Security.SecureString

The Script:

<#
    This script will take the exported file from PowerSchool
    and add the headers then process the file. 

    Any changes should be able to be made in the top block 
    environmental variables and paths.
#>

<# 
    Set our Preference Variables and
    create the transcript log
#>
$ErrorActionPreference="SilentlyContinue"
Stop-Transcript | out-null
$ErrorActionPreference = "Continue"
Start-Transcript -path latest.log

<#
    Adding old fallbacks just in case
#>
Import-Module ActiveDirectory -ErrorAction SilentlyContinue

<#
    Add any variables that we need 
    for the process here. 

    These should be able to be managed and changed easily 
    for any changes made throughout time.
#>
    $global:basePath = "C:\SftpRoot\loginid\"
    $global:fileName = "student-ad.csv"
    $global:csvPath = $basePath + $fileName
    $global:saveFile = "ADNEW.csv"
    $global:missingHeaders = @("last_name","first_name","middle_name","student_number","grade_level","schoolID") # Add all column headers here. 
    $global:subDomain = "student" # Email purposes only. Use "" if nothing.
    $global:studentGroups = '802.1x Student','Domain Users' # Add Groups in that the students should be added to.
    $global:schools = @(
        [pscustomobject]@{Name='ES';Grades=@('1','2','3','4')}
        [pscustomobject]@{Name='NW';Grades=@('1','2','3','4')}
        [pscustomobject]@{Name='SR';Grades=@('1','2','3','4')}
        [pscustomobject]@{Name='EC';Grades=@('PK','K')}
        [pscustomobject]@{Name='PI';Grades=@('5','6')}
        [pscustomobject]@{Name='MS';Grades=@('7','8')}
        [pscustomobject]@{Name='HS';Grades=@('9','10','11','12')}
    )
    $global:schoolName = $null
    # Build email path
    if($subDomain -eq "" -or $subDomain -eq $null){
        $global:emailPath = '@' + $env:USERDNSDOMAIN.ToLower()
    }else{
        $global:emailPath = '@' + $subDomain + '.' + $env:USERDNSDOMAIN.ToLower()
    }
<# /VARIABLES #>

<###########################################
    Add any functions/methods that we need 
    for the process here. 

    These should NOT be edited
###########################################>
<#
    Name: makePassword
    Params: $fn
            $mn
            $ln
            $sid

    Instructions: Call function and provide First Name,
    Middle Name, Last Name, and Student ID so we can 
    create the new student password.
#>
Function makePassword($fn,$mn,$ln,$sid){
    if($mn -eq $null -or $mn -eq ""){
        $pw = $fn.substring(0,1) + $mn.substring(0,1) + $ln.substring(0,1) + $sid
        return $pw
    }else{
        $pw = $fn.substring(0,1) + $ln.substring(0,1) + $sid
        return $pw
    }
} # END makePassword

<#
    Name: CreateOUs
    Params: NA

    Instructions: Call function to verify and create 
    Organizational Units in AD.
#>
Function CreateOUs() {
    # Create Inner Variables
    $sPath = 'DC='+$env:USERDNSDOMAIN.Substring(0,$env:USERDNSDOMAIN.Length-4)+',DC='+$env:USERDNSDOMAIN.Substring($env:USERDNSDOMAIN.Length-3)

    # Check for and create the Students OU first
    $studentsExists = ([adsi]::Exists("LDAP://OU=Students,$sPath"))

    if ($studentsExists -eq $true) {
        Write-Host "Students OU already exists." -foregroundcolor Yellow
    } else {
        Write-Host "Students OU being created."  -foregroundcolor Green
        $tPath = 'DC='+$env:USERDNSDOMAIN.Substring(0,$env:USERDNSDOMAIN.Length-4)+',DC='+$env:USERDNSDOMAIN.Substring($env:USERDNSDOMAIN.Length-3)
        New-ADOrganizationalUnit -Name 'Students' -Path $tPath -ProtectedFromAccidentalDeletion $true
    }

    # Check for the schools OU paths
    $schools | ForEach-Object {
        $scPath = 'OU=Students,DC='+$env:USERDNSDOMAIN.Substring(0,$env:USERDNSDOMAIN.Length-4)+',DC='+$env:USERDNSDOMAIN.Substring($env:USERDNSDOMAIN.Length-3)
        $scName = $_.'Name'

        $schoolExists = ([adsi]::Exists("LDAP://OU=$scName,$scPath"))

        if ($schoolExists -eq $True){
            Write-Host "$scName OU already exists." -foregroundcolor Yellow
        } else {
            Write-Host "$scName OU is being created." -foregroundcolor Green
            New-ADOrganizationalUnit -Name "$scName" -Path $scPath -ProtectedFromAccidentalDeletion $false
        }

        foreach($grade in $_.'Grades'){
            # Check for the grades OU paths
            $gradeExists = ([adsi]::Exists("LDAP://OU=$grade,OU=$scName,$scPath"))

            if ($gradeExists -eq $true) {
                Write-Host "$grade OU already exists." -foregroundcolor Yellow
            } else {
                Write-Host "$grade OU being created." -foregroundcolor Green
                $gPath = "OU=$scName,$scPath"
                New-ADOrganizationalUnit -Name $grade -Path $gPath -ProtectedFromAccidentalDeletion $false
            }
        }
    }

} # END CreateOUs

<#
    Name: CreateGroups
    Params: NA

    Instructions: Call function to verify and create 
    Organizational Groups in AD.
#>
Function CreateGroups() {
    # Check for and create the Groups in the provided array above
    $studentGroups | ForEach-Object {

        # Create Path variable
        $gPath = 'CN=Users,DC='+$env:USERDNSDOMAIN.Substring(0,$env:USERDNSDOMAIN.Length-4)+',DC='+$env:USERDNSDOMAIN.Substring($env:USERDNSDOMAIN.Length-3)
        $gName = $_

        $groupExists = try { [ADSI]::Exists('LDAP://CN=' + $gName + ',' + $gPath) } catch { $False }

        if($groupExists -eq $true){
            Write-Host "Group $gName already exists. Skipping..." -foregroundcolor Yellow
        }else{
            New-ADGroup -Name $gName -Path: $gPath -SamAccountName: $gName -GroupCategory: Security -GroupScope: Global
            Write-Host "Group $gName did not exsist. It has now been been created in $gPath" -foregroundcolor Green
        }
    }
} # END CreateGroups

<##################################
    This is where it all begins
##################################>
# Log the date
Get-Date

# Create the OUs if they don't exist
CreateOUs

# Create the Groups if they don't exist
CreateGroups

# Import out CSV file and process it
Import-Csv $csvPath -Header $missingHeaders | Select-Object `
    @{name='Name';expression={$_.'student_number'}}, `
    @{name='SamAccountName';expression={$_.'student_number'}}, `
    @{name='DisplayName';expression={($_.'first_name'+' '+$_.'last_name')}}, `
    @{name='GivenName';expression={$_.'first_name'}}, `
    @{name='Surname';expression={$_.'last_name'}}, `
    @{name='MiddleInitial';expression={($_.'middle_name').Substring(0,1)}}, `
    @{name='EmailAddress';expression={($_.'student_number'+$emailPath)}}, `
    @{name='Description';expression={$_.'student_number'}}, `
    @{name='Path';expression={"OU="+$_.'grade_level'+",OU="+$_.'schoolID'+",OU=Students,DC="+$env:USERDNSDOMAIN.Substring(0,$env:USERDNSDOMAIN.Length-4)+",DC="+$env:USERDNSDOMAIN.Substring($env:USERDNSDOMAIN.Length-3)}}, `
    @{name='PasswordNeverExpires';expression={$true}}, `
    @{name='Enabled';expression={$true}}, `
    @{name='ChangePasswordAtLogon';expression={$false}}, `
    @{name='AccountPassword';expression={ConvertTo-SecureString "makePassword $_.'first_name' $_.'middle_name' $_.'last_name' $_.'student_number'" -AsPlainText -force}} | 
    Out-GridView

<#
    Let's wrap it up now!!!

    Give the date (should be the same)
    and stop the transcript log. 
#>
# Log the date
Get-Date

# Stop the transcript log
Stop-Transcript
  • Here is a sample of how the data comes in. (student-ad.csv) Thumb,Tom,Tiny,11506,11,705
    Biden,Joe,Schmoe,11722,5,125
    Trump,Donald,,10405,8,510
    Jill,Jack,Paul,11215,6,125

When I try to change out the pipe cmdlet Out-GridView with New-ADUser I get the following output:

PS C:\Windows\System32\WindowsPowerShell\v1.0>student-ad.ps1
Transcript started, output file is latest.log

Wednesday, May 19, 2021 12:03:14 PM
Students OU already exists.
ES OU already exists.
1 OU already exists.
2 OU already exists.
3 OU already exists.
4 OU already exists.
NW OU already exists.
1 OU already exists.
2 OU already exists.
3 OU already exists.
4 OU already exists.
SR OU already exists.
1 OU already exists.
2 OU already exists.
3 OU already exists.
4 OU already exists.
EC OU already exists.
PK OU already exists.
K OU already exists.
PI OU already exists.
5 OU already exists.
6 OU already exists.
MS OU already exists.
7 OU already exists.
8 OU already exists.
HS OU already exists.
9 OU already exists.
10 OU already exists.
11 OU already exists.
12 OU already exists.
Group 802.1x Student already exists. Skipping...
Group Domain Users already exists. Skipping...
New-ADUser : Directory object not found
At C:\SftpRoot\loginid\student-ad.ps1:190 char:5
+     New-ADUser
+     ~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (CN=11506,OU=11,...DC=DEVDC,DC=COM:String) [New-ADUser], ADIdentityNotFoundException
    + FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,Microsoft.ActiveDirectory.Management.Commands.NewADUser

New-ADUser : Directory object not found
At C:\SftpRoot\loginid\student-ad.ps1:190 char:5
+     New-ADUser
+     ~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (CN=11722,OU=5,O...DC=DEVDC,DC=COM:String) [New-ADUser], ADIdentityNotFoundException
    + FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,Microsoft.ActiveDirectory.Management.Commands.NewADUser

What am I doin wrong and why is it trying to create a CN for the User rather than add them to the OU specified?

Windows for business | Windows Client for IT Pros | Directory services | Active Directory
Windows for business | Windows Server | User experience | PowerShell
0 comments No comments

Answer accepted by question author

Anonymous
2021-05-20T03:40:15.727+00:00

Hi,

In Line182, it's ”schoolID“ in the "Path" property but the OU is created with the "name" of $schools, so the directory cannot be found.

Best Regards,
Ian Xue

============================================

If the Answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

Was this answer helpful?

1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.