locked
Combine Get-ADComputer, Get-ADuser .. and optimalize the script RRS feed

  • Question

  • Hello,
    I need to optimize my script

    It should select all computer from AD, select attribute ManagedBy and for each user in managedby  it should search for mail,telephonenumber...  

    It is working, but i got errors when ManagedBy attribute is empty - because Get-ADUser requires its identity..

    Output should looks like:

    Name          ManagedBy   TelephoneNumber
    P011W7       user1          +420 123 456 789
    P012XP                                                   <=  (computer account is with empty managedby attribute.. )
    P013XP        user2          +420 558 555 555

    Also, i dont know if quering multiple times cmdlet get-aduser is efficient.   If i run this script for 4000 computer accounts, for each account quering 3+  get-aduser ... it would be slow. Any ideas how to optimize that? 

    Thanks

    $ComputerList = get-adcomputer -filter {(Name -like "P*") -or (Name -like "n*")} -properties * | ?{$_.OperatingSystem -notlike "*server*"} | select Name,@{n="Managedby";e={($_.Managedby -split ",*..=")[1]}}
    $Output = @()
    foreach ($PC in $ComputerList) {
    $MyObject = New-Object PSObject -Property @{
    PcName = $PC.Name
    ManagedBy = $PC.Managedby
    UserEnabled = (get-aduser -identity $PC.ManagedBy).Enabled
    PrimarySMTP = (get-aduser -identity  $PC.Managedby -properties *).Mail
    Phone = (get-aduser -identity  $PC.Managedby -properties * ).telephoneNumber
    }
    $Output += $MyObject
    }
    $Output

    Friday, November 2, 2012 10:37 AM

Answers

  • $ComputerList = get-adcomputer -filter {(Name -like "P*") -or (Name -like "n*") -and OperatingSystem -notlike "*server*" } -Properties managedby | Group managedby
    
    $Output = @()
    foreach ($PC in $ComputerList) {
    	$user = [ADSI]"LDAP://$($PC.Name)" 
    	$PC.Group | Foreach {
    		$Output += New-Object PSObject -Property @{
    			PcName = $_.Name
    			ManagedBy = $(if($_.ManagedBy) {$user.Name})
    			UserEnabled = $(if($_.ManagedBy){![bool]($user.userAccountControl.value -band 2)})
    			PrimarySMTP = $(if($_.ManagedBy){$user.mail})
    			Phone = $(if($_.ManagedBy){$user.telephoneNumber})
    		}
    	}
    }








    • Edited by Kazun Friday, November 2, 2012 12:05 PM
    • Proposed as answer by Jaap BrasserMVP Friday, November 2, 2012 12:25 PM
    • Marked as answer by Mekac Wednesday, April 24, 2013 5:54 AM
    Friday, November 2, 2012 11:36 AM
  • $ComputerList = get-adcomputer -filter {((Name -like "P*") -or (Name -like "n*")) -and (OperatingSystem -notlike "*server*")} -properties Name,Managedby | select Name,@{n="Managedby";e={($_.Managedby -split ",*..=")[1]}}
    $Output = @()
    foreach ($PC in $ComputerList) {
    
       $PcName = $PC.Name
       $ManagedBy = $PC.Managedby
       if ($ManagedBy) {
    	$user = get-aduser -identity $ManagedBy -Properties Enabled,Mail,telephoneNumber
    	$UserEnabled = $user.Enabled
    	$PrimarySMTP = $user.Mail
    	$Phone = $user.telephoneNumber
    
    	$MyObject = New-Object PSObject -Property @{
    		PcName = $PC.Name
    		ManagedBy = $Managedby
    		UserEnabled = $UserEnabled
    		PrimarySMTP = $PrimarySMTP
    		Phone = $Phone
    	}
       }else
      {
    	$MyObject = New-Object PSObject -Property @{
    		PcName = $PC.Name
    		ManagedBy = ""
    		UserEnabled = ""
    		PrimarySMTP = ""
    		Phone = ""
    	}
       }
    
    $Output += $MyObject
    
    }
    $Output
    


    Сазонов Илья http://isazonov.wordpress.com/

    • Marked as answer by Mekac Friday, November 2, 2012 12:52 PM
    Friday, November 2, 2012 11:57 AM

All replies

  • How large is your set of unique managers?

    If it's relatively small, you can optimize it by creating a hash table of the managers DNs and telephone numbers to use as a lookup cache.

    Check the ManagedBy DNs against that hash table first.  If it finds an entry there, use that to get the phone number.  If it doesn't find it, do a lookup and then add it to the hash table.  That way, you only do the lookuup on any given manager once. The UserEnabled, PrimarySMTP

     

    Edit: Looking back at the script, you can avoid doing three lookups by doing one lookup on the manager and storing it to a variable.  The output sample does not agree with code you posted.  The ManagedBy in the report is a CN, but the property value is a DN, and the output does not include the UserEnabled or PrimarySMTP properties. 


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "


    • Edited by mjolinor Friday, November 2, 2012 11:15 AM
    Friday, November 2, 2012 11:07 AM
  • $ComputerList = get-adcomputer -filter {(Name -like "P*") -or (Name -like "n*") -and OperatingSystem -notlike "*server*" } -Properties managedby | Group managedby
    
    $Output = @()
    foreach ($PC in $ComputerList) {
    	$user = [ADSI]"LDAP://$($PC.Name)" 
    	$PC.Group | Foreach {
    		$Output += New-Object PSObject -Property @{
    			PcName = $_.Name
    			ManagedBy = $(if($_.ManagedBy) {$user.Name})
    			UserEnabled = $(if($_.ManagedBy){![bool]($user.userAccountControl.value -band 2)})
    			PrimarySMTP = $(if($_.ManagedBy){$user.mail})
    			Phone = $(if($_.ManagedBy){$user.telephoneNumber})
    		}
    	}
    }








    • Edited by Kazun Friday, November 2, 2012 12:05 PM
    • Proposed as answer by Jaap BrasserMVP Friday, November 2, 2012 12:25 PM
    • Marked as answer by Mekac Wednesday, April 24, 2013 5:54 AM
    Friday, November 2, 2012 11:36 AM
  • $ComputerList = get-adcomputer -filter {((Name -like "P*") -or (Name -like "n*")) -and (OperatingSystem -notlike "*server*")} -properties Name,Managedby | select Name,@{n="Managedby";e={($_.Managedby -split ",*..=")[1]}}
    $Output = @()
    foreach ($PC in $ComputerList) {
    
       $PcName = $PC.Name
       $ManagedBy = $PC.Managedby
       if ($ManagedBy) {
    	$user = get-aduser -identity $ManagedBy -Properties Enabled,Mail,telephoneNumber
    	$UserEnabled = $user.Enabled
    	$PrimarySMTP = $user.Mail
    	$Phone = $user.telephoneNumber
    
    	$MyObject = New-Object PSObject -Property @{
    		PcName = $PC.Name
    		ManagedBy = $Managedby
    		UserEnabled = $UserEnabled
    		PrimarySMTP = $PrimarySMTP
    		Phone = $Phone
    	}
       }else
      {
    	$MyObject = New-Object PSObject -Property @{
    		PcName = $PC.Name
    		ManagedBy = ""
    		UserEnabled = ""
    		PrimarySMTP = ""
    		Phone = ""
    	}
       }
    
    $Output += $MyObject
    
    }
    $Output
    


    Сазонов Илья http://isazonov.wordpress.com/

    • Marked as answer by Mekac Friday, November 2, 2012 12:52 PM
    Friday, November 2, 2012 11:57 AM
  • Good stuff Kazun, using [adsi] is a big time saver here. A minor modification would to use [adsisearcher] with an LDAP query instead of Get-ADComputer, that way you can be completely independent of the AD Cmdlets, something along the lines of:

    ([adsisearcher]'(&(&(objectclass=computer)(!OperatingSystem=*server*))(|(name=p*)(name=n*)))').findall()


    Jaap Brasser
    http://www.jaapbrasser.com

    Friday, November 2, 2012 12:25 PM
  • Hello Kazun,

    your script work. - only slight minor issues there.

    $ComputerList = get-adcomputer -filter {(Name -like "P*") -or (Name -like "n*") -and OperatingSystem -notlike "*server*" }

    .. missing ()  in operatingSystem -notlike

    $ComputerList = get-adcomputer -filter {(Name -like "P*") -or (Name -like "n*") -and (OperatingSystem -notlike "*server*")}

    And.. some computers have the same manager.  Couse of that, output is kinda multiplied. I think that pc.group |foreach needs to rework.   It looks like:


    ManagedBy               Phone              PcName       UserEnabled PrimarySMTP
    ---------               -----                   ------           ----------- -----------
    user1            {+420 999 999 999}      NUser1           True            {e-mail}
    user1            {+420 999 999 999}      Nuser1           True            {e-mail}
    user2            {+420 999 999 999}      Nuser2           True            {e-mail}
    user1            {+420 999 999 999}      Nuser1           True            {e-mail}
    user2            {+420 999 999 999}      Nuser2           True            {e-mail}
                                                         Nuser3

    It should look like  (only 1 notebook for each user there)
    user1                 {+420 999 999 999}      NUser1                                 True {e-mail}
    user2                   {+420 999 999 999}    Nuser2                                 True {e-mail}
                                                              Nuser3

    On AD, there is only Nuser1, Nuser2, Nuser3   computers..  so why multiple lines for user1 and user2?

    Friday, November 2, 2012 12:46 PM
  • Thank you,
    it made the needed output.

    Sincerely,

    Mekac

    Friday, November 2, 2012 12:50 PM
  • Hello Kazun,

    your script work. - only slight minor issues there.

    $ComputerList = get-adcomputer -filter {(Name -like "P*") -or (Name -like "n*") -and OperatingSystem -notlike "*server*" }

    .. missing ()  in operatingSystem -notlike

    $ComputerList = get-adcomputer -filter {(Name -like "P*") -or (Name -like "n*") -and (OperatingSystem -notlike "*server*")}

    And.. some computers have the same manager.  Couse of that, output is kinda multiplied. I think that pc.group |foreach needs to rework.   It looks like:


    ManagedBy               Phone              PcName       UserEnabled PrimarySMTP
    ---------               -----                   ------           ----------- -----------
    user1            {+420 999 999 999}      NUser1           True            {e-mail}
    user1            {+420 999 999 999}      Nuser1           True            {e-mail}
    user2            {+420 999 999 999}      Nuser2           True            {e-mail}
    user1            {+420 999 999 999}      Nuser1           True            {e-mail}
    user2            {+420 999 999 999}      Nuser2           True            {e-mail}
                                                         Nuser3

    It should look like  (only 1 notebook for each user there)
    user1                 {+420 999 999 999}      NUser1                                 True {e-mail}
    user2                   {+420 999 999 999}    Nuser2                                 True {e-mail}
                                                              Nuser3

    On AD, there is only Nuser1, Nuser2, Nuser3   computers..  so why multiple lines for user1 and user2?


    Because you run code twice.
    Friday, November 2, 2012 12:55 PM