Hash Table with validation / IF / Else

This topic contains 15 replies, has 5 voices, and was last updated by Profile photo of Peter Jurgens Peter Jurgens 3 months, 1 week ago.

  • Author
    Posts
  • #64296
    Profile photo of Stuart
    Stuart
    Participant

    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

  • #64303
    Profile photo of Matt Bloomfield
    Matt Bloomfield
    Participant

    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.

    • #64350
      Profile photo of Stuart
      Stuart
      Participant

      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

  • #64306
    Profile photo of Ron
    Ron
    Participant

    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)
    }
    
    • #64354
      Profile photo of Stuart
      Stuart
      Participant

      Thank you

  • #64318
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    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
    
    • #64356
      Profile photo of Stuart
      Stuart
      Participant

      Awesome, looks good, I'll try this now, thank you

  • #64357
    Profile photo of Stuart
    Stuart
    Participant

    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

  • #64360
    Profile photo of Stuart
    Stuart
    Participant

    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

    • #64656
      Profile photo of Peter Jurgens
      Peter Jurgens
      Participant

      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.

  • #64386
    Profile photo of Stuart
    Stuart
    Participant

    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

  • #64449
    Profile photo of Stuart
    Stuart
    Participant

    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

  • #64459
    Profile photo of Ron
    Ron
    Participant

    Try this:

    $hash.Add("Description", ($_).description)

    • #64504
      Profile photo of Stuart
      Stuart
      Participant

      perfect, may I ask, why is it necessary to put the '$_' into brackers just because its a pipeline var?

    • #64560
      Profile photo of Ron
      Ron
      Participant

      I don't know the exact technical reason, it has something to do with the order of evaluation inside of the function call.

  • #64659
    Profile photo of Peter Jurgens
    Peter Jurgens
    Participant

    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.

You must be logged in to reply to this topic.