none
Having trouble properly looping through a hashtable RRS feed

  • Question

  • I am trying to import a csv file with user info which then writes values to a hashtable which is then appended to a master hashtable..

    i want to be able to then loop through the master hash table in a foreach loop.. i have the script below and it will properly create the master hashtable with the two other hashtables in it.. but when i want to loop through that master hash i get only the 2nd users details.  any help would be appreciated.

    $i = $null
    $users = Import-Csv C:\powershell\Create_AD_Users.csv
    $hashtable = $null
    $hashtable = @{}
    $minihash = $null
    $minihash = @{}
    foreach ($user in $users)
    {
    $i++
    $first = $user.firstname
    $last = $user.lastname
    $minihash =  @{'First'= $first;'last'=$last}
    $hashtable.Add('minihash'+"$i",$minihash)
    }
    
    $hashtable.GetEnumerator() | ForEach-Object{
    
    
    $first
    
    }

    Tuesday, November 10, 2015 8:51 PM

Answers

  • Kept playing with it and came up with the below.  I opted to not use the above example as i couldn't see a way to get the upn generated without passing it from the first loop into a hashtable that gets called by the second loop.  seems to give me what i want..i am sure the PowerShell Ninjas of the world will tear it apart :)

    $i = $null
    $users = Import-Csv c:\powershell\Create_AD_Users.csv
    $hashtable = $null
    $hashtable = @{}
    $minihash = $null
    $minihash = @{}
    foreach ($user in $users)
    {
    $i++
    $first = $user.firstname
    $last = $user.lastname
    $mailenabled = $user.MailEnabled
    $upn = "$first.$last"+"@company.com"
    #other custom user variables are also created here
    If ($mailenabled -eq $true)
      {
       $minihash =  @{'First'= $first;'last'=$last;'UPN'= $upn}
       $hashtable.Add('minihash'+"$i",$minihash)
      }
    }
    
    Foreach ($Key in ($hashtable.GetEnumerator()))
    {
    #do something with these values
    $key.Value.First
    $key.Value.last
    $key.Value.UPN
    
    }


    • Edited by escott0699 Tuesday, November 10, 2015 11:44 PM missing }
    • Marked as answer by escott0699 Wednesday, November 11, 2015 1:29 PM
    Tuesday, November 10, 2015 11:37 PM

All replies

  • 

    Juan is the 2nd user in the csv file

    Tuesday, November 10, 2015 8:53 PM
  • Why not just use the objects that you get from Import-Csv?

    What's your actual goal here? Not how you think you need to do it, but what you're actually trying to accomplish.


    Tuesday, November 10, 2015 8:56 PM
  • I am using the import-csv in an earlier loop but that loop filters itself down based on whether or not the user is getting  a mailbox in exchange.. so i don't want to pass all csv users to the hashtable...
    Tuesday, November 10, 2015 8:58 PM
  • I am using the import-csv in an earlier loop but that loop filters itself down based on whether or not the user is getting  a mailbox in exchange.. so i don't want to pass all csv users to the hashtable...

    I have no idea what you mean by this.

    Good luck.


    Tuesday, November 10, 2015 9:03 PM
  • How do you know when a user is getting a mailbox?  Is ther some magical thing that happens.  Remember  that computers don't get along well with magic.  THey are pretty dumb when it comes to that.

    Tell us how you know that,

    A CSV filter looks like this:

    Import-Csv file.csv| ?{$_.HasMail -eq 'True'}

    This filters on a single field.


    \_(ツ)_/

    Tuesday, November 10, 2015 9:09 PM
  • sorry let me clarify a little...

    this is small snipet of code from a larger user creation script.  This script will use two foreach loops ideally.  The first loop imports the csv file and creates unique info like usernames, email addresses etc.. that are not in the csv to begin with.  So i need to pass along those csv and new unique attributes to the hashtable to prevent having to export and import a new csv with the combined original and new attributes and then loop through the hashtable as though it's a csv file to enable mailboxes etc in Office 365.  I could in theory do it all in one big foreach loop, but with user replication times it bloats the run time to multiple hours.  So it would be better to do all the local AD stuff in one loop then the Office 365 stuff in another loop..hope that clarifies it

    Tuesday, November 10, 2015 9:31 PM
  • yes the csv file does have a mailenabled (true or false) requirement.  if true it passes the new user info to the hashtable...

    this is small snipet of code from a larger user creation script.  This script will use two foreach loops ideally.  The first loop imports the csv file and creates unique info like usernames, email addresses etc.. that are not in the csv to begin with.  So i need to pass along those csv and new unique attributes to the hashtable to prevent having to export and import a new csv with the combined original and new attributes and then loop through the hashtable as though it's a csv file to enable mailboxes etc in Office 365.  I could in theory do it all in one big foreach loop, but with user replication times it bloats the run time to multiple hours.  So it would be better to do all the local AD stuff in one loop then the Office 365 stuff in another loop..hope that clarifies it

    • Edited by escott0699 Tuesday, November 10, 2015 9:33 PM
    Tuesday, November 10, 2015 9:33 PM
  • There is no need too do it like that.  There is no "bloating".  The loop will run at the same speed no matter how you do it. Why complicate an easy thing.

    Given that - what is your issue?  You have not really asked a question.

    Why do all new users always want to build hash tables.  Hash tables are not what we use.  We use objects.  A hash table is just a simple way to generate an object.

    You also didn't answer how you know that the user has/doesn't email or what you are filtering on.

    Import-Csv file.csv | ?{ <filter> } |
    ForEach-Object{
    	$props = @{
    		... here we add all new user properties by name
    		FirstName=$_.first
    		FullName='{} {}' -f $_.first, $_.Last
    		PrimaryEmailAddress= ....
        }
    	New-User @Props
    }
    
    #Alternate
    $prepped=Import-Csv file.csv | ?{ <filter> } |
    ForEach-Object{
    	$props = @{
    		... here we add all new user properties by name
    		FirstName = $_.first
    		FullName = '{} {}' -f $_.first, $_.Last
    		PrimaryEmailAddress = ....
    	}
    	[pscustomobject]$Props
    } 


    \_(ツ)_/



    • Edited by jrv Tuesday, November 10, 2015 9:43 PM
    Tuesday, November 10, 2015 9:43 PM
  • yes the csv file does have a mailenabled (true or false) requirement.  if true it passes the new user info to the hashtable...

    this is small snipet of code from a larger user creation script.  This script will use two foreach loops ideally.  The first loop imports the csv file and creates unique info like usernames, email addresses etc.. that are not in the csv to begin with.  So i need to pass along those csv and new unique attributes to the hashtable to prevent having to export and import a new csv with the combined original and new attributes and then loop through the hashtable as though it's a csv file to enable mailboxes etc in Office 365.  I could in theory do it all in one big foreach loop, but with user replication times it bloats the run time to multiple hours.  So it would be better to do all the local AD stuff in one loop then the Office 365 stuff in another loop..hope that clarifies it


    prepped=Import-Csv file.csv | ?{ $_.mailenabled -eq 'true' } |
    ForEach-Object{
    	$props = @{
    		... here we add all new user properties by name
    		FirstName = $_.first
    		FullName = '{} {}' -f $_.first, $_.Last
    		PrimaryEmailAddress = ....
    	}
    	[pscustomobject]$Props
    } 


    \_(ツ)_/

    • Proposed as answer by SitrucHtims Wednesday, November 11, 2015 3:53 AM
    Tuesday, November 10, 2015 9:46 PM
  • To apply:

    $prepped | %{New-User @($_)}


    \_(ツ)_/

    Tuesday, November 10, 2015 9:47 PM
  • Actually it does bloat the script time quite a bit.  when an AD user is created it takes 15-20 minutes to replicate to office 365 and then you have to wait for replication on other areas as you update the office 365 account.  it makes more sense to create all users in AD first..let that replicate using a while loop to wait for the user accounts to show up then run a 2nd loop to do the office 365 piece.. and please note above where i mention that the csv file for the real script has mailenabled = true or false...

    If a hash table isn't the way to do it then do tell..one big loop will not work for us.

    Tuesday, November 10, 2015 9:47 PM
  • Thanks but i would really prefer to not have to import the csv a 2nd time as the first foreach loop creates some new custom attributes like samaccountname and upn..so having to redo the logic in the 2nd foreach loop doesn't make much sense to me.. if i am looking at this wrong please let me know.

    Thanks

    Tuesday, November 10, 2015 9:51 PM
  • The second example does NOT create a CSV.

    \_(ツ)_/

    Tuesday, November 10, 2015 9:59 PM
  • perhaps i am getting confused here...

    i see it doesn't create a new csv but it is importing a csv in both examples above.. and importing the csv the 2nd time is where is the trouble for comes in as my csv does not hold all the new unique data that my first foreach loop created when generating the AD account..

    so whether it's a hashtable or someother way i need to pass the new attributes that are not available in an import-csv


    • Edited by escott0699 Tuesday, November 10, 2015 10:03 PM
    Tuesday, November 10, 2015 10:02 PM
  • Both examples are for the first pass.  Here is the second "loop" as you call it.

    $prepped | %{ ... do OO365 things ...}


    \_(ツ)_/

    Tuesday, November 10, 2015 10:09 PM
  • Kept playing with it and came up with the below.  I opted to not use the above example as i couldn't see a way to get the upn generated without passing it from the first loop into a hashtable that gets called by the second loop.  seems to give me what i want..i am sure the PowerShell Ninjas of the world will tear it apart :)

    $i = $null
    $users = Import-Csv c:\powershell\Create_AD_Users.csv
    $hashtable = $null
    $hashtable = @{}
    $minihash = $null
    $minihash = @{}
    foreach ($user in $users)
    {
    $i++
    $first = $user.firstname
    $last = $user.lastname
    $mailenabled = $user.MailEnabled
    $upn = "$first.$last"+"@company.com"
    #other custom user variables are also created here
    If ($mailenabled -eq $true)
      {
       $minihash =  @{'First'= $first;'last'=$last;'UPN'= $upn}
       $hashtable.Add('minihash'+"$i",$minihash)
      }
    }
    
    Foreach ($Key in ($hashtable.GetEnumerator()))
    {
    #do something with these values
    $key.Value.First
    $key.Value.last
    $key.Value.UPN
    
    }


    • Edited by escott0699 Tuesday, November 10, 2015 11:44 PM missing }
    • Marked as answer by escott0699 Wednesday, November 11, 2015 1:29 PM
    Tuesday, November 10, 2015 11:37 PM