none
For Loop, Nested If Statement, Variable Problem RRS feed

  • Question

  • I am trying to write a script to audit our Active Directory users departments against information provided by our HR department.
    The basics of the script are as follows:

    Import-Module activedirectory
    
    $hr = Import-Csv E:\hr_data.csv
    
    $ad = Get-ADUser -Filter * -Properties * `
    | ? { $_.employeenumber -ne $null } `
    | select samaccountname,department,title,@{L='deptnumber'; E={$_.departmentnumber}},employeenumber `
    | sort employeenumber
    
    For ($k = 0; $k -lt $hr.count; $k++) {						
     $comp = $ad | ? {$_.employeenumber -eq $hr[$k]."EmpNumber" }   				# find matching user in AD via employeeNumber
     If ( $comp.deptnumber -ne $hr[$k].dNumber) {           # if department numbers don't match, update
      Set-ADUser -Identity $comp.samaccountname -Replace -replace @{departmentNumber=$hr[$k].dNumber}
     }
    }

    Where I seem to be having issues is the Set-ADUser command is failing to recognize $comp.samaccountname.
    If I substitute Write-Output $comp.samaccountname for the Set-ADUser command, it gives the correct value. 
    If I modify the loop as follows:

    For ($k = 0; $k -lt $hr.count; $k++) {						
     $comp = $ad | ? {$_.employeenumber -eq $hr[$k]."EmpNumber" } 
     Get-ADUser $comp.samaccountname | select Name  				
     If ( $comp.deptnumber -ne $hr[$k].dNumber) {            
      Get-ADUser $comp.samaccountname | select Name
     }
    }
    The outer Get-ADUser command succeeds but the one nested in the IF statement fails.
    Any ideas?

    Thursday, March 24, 2016 9:22 PM

Answers

  • It will work better if you don't do it backwards:

    Import-Module activedirectory
    
    $hr = Import-Csv E:\hr_data.csv
    Get-ADUser -Filter {EmployeeNumber -like '*'} -Properties * |
    ForEach-Object{
    	$user=$_
    	if ($dept = $hr | ?{ $_.empNumber -eq $user.EmployeeNumber }) {
    		If ($user.deptnumber -ne $dept) {
    			Set-ADUser -Identity $user.samaccountname -Replace @{ departmentNumber = $dept }
    		}
    	} else {
    		Write-Host 'Emplyee not found' -fore Red
    	}
    }


    \_(ツ)_/

    • Marked as answer by Markus Adler Thursday, April 7, 2016 7:58 PM
    Thursday, March 24, 2016 9:45 PM

All replies

  • It will work better if you don't do it backwards:

    Import-Module activedirectory
    
    $hr = Import-Csv E:\hr_data.csv
    Get-ADUser -Filter {EmployeeNumber -like '*'} -Properties * |
    ForEach-Object{
    	$user=$_
    	if ($dept = $hr | ?{ $_.empNumber -eq $user.EmployeeNumber }) {
    		If ($user.deptnumber -ne $dept) {
    			Set-ADUser -Identity $user.samaccountname -Replace @{ departmentNumber = $dept }
    		}
    	} else {
    		Write-Host 'Emplyee not found' -fore Red
    	}
    }


    \_(ツ)_/

    • Marked as answer by Markus Adler Thursday, April 7, 2016 7:58 PM
    Thursday, March 24, 2016 9:45 PM
  • Thanks for the code and sorry for the slow response, been a couple of short weeks due to holidays.

    I suspect I've missed something in my explanation as what you provided only gives half the expected results.

    There are certain users in the HR system that don't exist in Active Directory and vice versa but it seems your code should already anticipate that.

    Monday, April 4, 2016 8:00 PM
  • Trying to do an exclusive OR operation on two different datasets is always fun. It would have helped if you'd mentioned that, it wasn't clear from your question.

    As to your first question, double check your results. You're more likely to be making a mistake than the computer is.

    Also, those are terrible variable names. What is $comp? Why are you calling a collection of user objects $ad? It's always a bad sign when people use unhelpful variable names and it makes trying to decrypt your script much harder. It also often directly causes mistakes when you make invalid assumptions.

    Now, working off jrv's code: once you've run the first batch you've identified any users who are in both system but need updating, and have updated them.

    You've identified any users who are in AD but not in the HR dataset, now you need to identify users in the HR dataset but not in AD. You could be clever and try to merge that in with the first operation but bluntly you'll waste more time 'optimising' it than you'll ever save running it. Just loop through the HR users and check each one against AD.


    Monday, April 4, 2016 10:18 PM
  • Trying to do an exclusive OR operation on two different datasets is always fun. It would have helped if you'd mentioned that, it wasn't clear from your question.

    As to your first question, double check your results. You're more likely to be making a mistake than the computer is.

    Also, those are terrible variable names. What is $comp? Why are you calling a collection of user objects $ad? It's always a bad sign when people use unhelpful variable names and it makes trying to decrypt your script much harder. It also often directly causes mistakes when you make invalid assumptions.

    Now, working off jrv's code: once you've run the first batch you've identified any users who are in both system but need updating, and have updated them.

    You've identified any users who are in AD but not in the HR dataset, now you need to identify users in the HR dataset but not in AD. You could be clever and try to merge that in with the first operation but bluntly you'll waste more time 'optimising' it than you'll ever save running it. Just loop through the HR users and check each one against AD.



    Also a very interesting set of questions.  I bet the answer IS the answer.

    \_(ツ)_/

    Monday, April 4, 2016 10:29 PM
  • Thanks jrv.

    Alex was correct in that I was pulling data from a bad source, getting the proper results now.

    Thursday, April 7, 2016 8:01 PM