Home > OS >  I am unable to get splatting to work with New-ADUser using given and created attributes
I am unable to get splatting to work with New-ADUser using given and created attributes

Time:04-06

I am processing an array of AD User data pulled from one domain to recreate in another. I have created a hash table linking the New-ADUser parameters with the user data imported from a CSV (populated from the domain I intend to recreate). When I call New-ADUser with the hash table, the user is not created and there are no error.

Here is the hash table:

$NewUserAttr = @{
    'Name'              = $ADUser.UsersName
    'SamAccountName'    = $ADUser.UsersSamAccountName
    'Company'           = $ADUser.UsersCompany
    'Department'        = $ADUser.UsersDepartment
    'DisplayName'       = $ADUser.UsersDisplayName
    'EmailAddress'      = $ADUser.UsersMail
    'EmployeeID'        = $ADUser.UsersEmployeeID
    'Enabled'           = $UsersEnabled
    'GivenName'         = $ADUser.UsersGivenName
    'Initials'          = $ADUser.UsersInitials
    'Manager'           = $ADUser.Manager
    'MobilePhone'       = $ADUser.UsersMobileNum
    'OfficePhone'       = $ADUser.UsersTelephoneNumber
    'PostalCode'        = $ADUser.UsersPostalCode
    'State'             = $ADUser.UsersST
    'StreetAddress'     = $ADUser.UsersStreetAddress
    'Surname'           = $ADUser.UsersSN
    'Title'             = $ADUser.UsersTitle
    'userPrincipalname' = $ADUser.UsersUPN
    'Path'              = $ParentOU
    'Server'            = $TargetDomain

    'OtherAttr' = @{
        'c'                  = $ADUser.Usersc
        'GIDNumber'          = $ADUser.UsersGIDNumber
        'l'                  = $ADUser.UsersL
        'LoginShell'         = $ADUser.UsersLoginShell
        'msSFU30Name'        = $ADUser.UsersMsSFU30Name
        'msSFU30NisDomain'   = $ADUser.UsersMsSFU30NisDomain
        'PhysicalDeliveryOfficeName' = $ADUser.UsersPhysicalDeliveryOfficeName
        'SSN'                = $ADUser.UsersSSN
        'Uid'                = $ADUser.UsersUid
        'uidNumber'          = $ADUser.UsersUidNum
        'unixHomeDirectory'  = $ADUser.UsersUHD
    }
}

PS > New-ADUser @NewUserAttr

I have reduced the NewUserAttr to Name, SamAccountName, Path, and Server and that did create the user, but that is far less parameters than what I need.

CodePudding user response:

Continuing from my comments:

To avoid empty fields from being assembled in the attributes Hashtable to use for splatting, you could create two lookup tables in which you  map the CSV header names with the actual AD user attribute names.
Something like this:

    # create two mapping lookup Hashtables for 'normal' attributes and one for the OtherAttributes
    # format is: PropertyNameFromCsv = PropertyNameForActiveDirectory
    $attribMap = @{
        UsersName           = 'Name'
        UsersSamAccountName = 'SamAccountName'
        UsersCompany        = 'Company'
        Usersc              = 'Country'
        Manager             = 'Manager'
        # etc.
    }

    $otherMap = @{
        UsersGIDNumber        = 'GIDNumber'
        UsersLoginShell       = 'LoginShell'
        UsersmsSFU30Name      = 'MsSFU30Name'
        UsersmsSFU30NisDomain = 'MsSFU30NisDomain'
        # etc.
    }

Next, import the CSV and loop over each entry:

$csv = Import-Csv -Path 'X:\your_importFile.csv'

foreach ($item in $csv) {
    # two empty Hashtables for splatting
    $NewUserAttr = @{}
    $OtherAttr   = @{}
    # pre fill the default attributes you need for all users
    $NewUserAttr['Enabled'] = $UsersEnabled
    $NewUserAttr['Server']  = $TargetDomain
    $NewUserAttr['Path']    = $ParentOU

    # loop over the properties for each item in the CSV and only store 
    # the ones that are not empty and for which you can find a mapping
    $item.PsObject.Properties | ForEach-Object {
        if (![string]::IsNullOrWhiteSpace($_.Value)) { 
            if ($attribMap.Contains($_.Name))    { $NewUserAttr[$attribMap[$_.Name]] = $_.Value }
            elseif ($otherMap.Contains($_.Name)) { $OtherAttr[$otherMap[$_.Name]] = $_.Value }
        }
    }
    # join the hashtables together if we have OtherAttributes
    if ($otherMap.Count) { $NewUserAttr['OtherAttributes'] = $OtherAttr }

    # now try and create the new user
    try {
        New-ADUser @NewUserAttr -ErrorAction Stop
    }
    catch {
        Write-Warning "Error creating user $($NewUserAttr.Name): $($_.Exception.Message)"
    }
}

CodePudding user response:

I run into this often with named parameters and null values. To avoid null values for your named parameters which $null indicates the parameter should be omitted rather than provided, follow these rules when creating the splat-hashtable:

  1. When defining the hashtable, define any properties that will not (or should not be) $null, like so:

    $splatArgs = @{
      ParameterOne = 'Value'
      ParameterTwo = 'OtherValue'
    }
    
  2. For parameters that may or may not need to be provided based on whether its value is $null (or evaluates falsey), conditionally add it to the hashtable:

    if( $someVar ) {
      $splatArgs.ConditionalParameter = $someVar
    }
    

Repeat 2. for each conditional argument you have. Alternatively, you could initialize the hashtable with all possible parameter names and values, then strip them out after after checking falsiness, comparing to $null, etc.

  # You could do any condition here but in this example,
  # We will do a simple falsiness test on each key's value
  $removeParameterNames = $splatArgs.Keys | Where-Object {
    !( $splatArgs.$_ )
  }

  # Use another loop here since we don't want to modify the hashtable
  # while iterating over its keys
  foreach( $key in $removeParameterNames ) {
    $splatArgs.Remove($key)
  }

CodePudding user response:

Here is what I ended up getting to work, which is very similar to what Bender recommended and what Richard from the link in my above comments recommended.

$NewUserAttr = @{
    'Name'                  = $ADUser.UsersName
    'SamAccountName'        = $ADUser.UsersSamAccountName
    'AccountPassword'       = (ConvertTo-SecureString -AsPlainText "<Ab@1Cd!2>" -Force)
    'Company'               = $ADUser.UsersCompany
    'Department'            = $ADUser.UsersDepartment
    'DisplayName'           = $ADUser.UsersDisplayName
    'EmailAddress'          = $ADUser.UsersMail 
    'EmployeeID'            = $ADUser.UsersEmployeeID
    'Enabled'               = $UsersEnabled
    'GivenName'             = $ADUser.UsersGivenName
    'MobilePhone'           = $ADUser.UsersMobileNum 
    'OfficePhone'           = $ADUser.UsersTelephoneNumber 
    'SurName'               = $ADUser.UsersSN 
    'Title'                 = $ADUser.UsersTitle
    'userPrincipalname'     = $ADUser.UsersUPN
    'Path'                  = $ParentOU
    'Server'                = $TargetDomain

    'OtherAttr' = @{
        'GIDNumber'                     = $ADUser.UsersGIDNumber
        'LoginShell'                    = $ADUser.UsersLoginShell
        'msSFU30Name'                   = $ADUser.UsersMsSFU30Name
        'msSFU30NisDomain'              = $ADUser.UsersMsSFU30NisDomain
        'Uid'                           = $ADUser.UsersUid
        'uidNumber'                     = $ADUser.UsersUidNum
        'unixHomeDirectory'             = $ADUser.UsersUHD
    } 
}

# Check the uncommon attributes and add them to the hash table if not null
if($ADUser.Usersl){$NewUserAttr.add('City',$ADUser.Usersl)}
if($ADUser.Usersc){$NewUserAttr.add('Country',$ADUser.Usersc)}
if($ADUser.UsersInitials){$NewUserAttr.add('Initials',$ADUser.UsersInitials)}
if($ADUser.Manager){$NewUserAttr.add('Manager',$ADUser.Manager)}
if($ADUser.UsersPostalCode){$NewUserAttr.add('PostalCode',$ADUser.UsersPostalCode)}
if($ADUser.UsersST){$NewUserAttr.add('State',$ADUser.UsersST)}
if($ADUser.UsersStreetAddress){$NewUserAttr.add('StreetAddress',$ADUser.UsersStreetAddress)}
if($ADUser.physicaldeliveryofficename){$NewUserAttr.OtherAttr.add('physicaldeliveryofficename',$ADUser.physicaldeliveryofficename)}
if($ADUser.UsersSSN){$NewUserAttr.OtherAttr.add('SSN',$ADUser.UsersSSN)}

#Add new user to destination domain
try {
    $UserExists = Get-ADUser -Identity $ADUser.UsersName -Server $TargetDomain
    if ($UserExists) {
        "Exists,$($ADUser.UsersName),$ParentOU`n" | Out-File $UserCreationLog -Append -Force
    } else {
        New-ADUser @NewUserAttr -ErrorAction Continue
        #Change password
        "Added,$($ADUser.UsersSamAccountName),$($ADUser.UsersName),$ParentOU`n" | Out-File $UserCreationLog -Append -Force
    }
} catch {
    $ErrorMsg = $_.Exception.Message
    Write-Log -Message "Unable to create user, $($ADUser.UsersName): $ErrorMsg." -Severity Error -LogPath $LogFile
    Write-Log -Message "Failed users attributes: $NewUserAttr $($NewUserAttr.OtherAttr)" -Severity Error -LogPath $LogPath
}

Now I just need to test each of these suggest answers to see which is the fastest! Thanks everyone!!

  • Related