none
Dynamic count (histogram) of discovered values in AD attribute

    Question

  • Hi All.  Thanks in advanced.

    I have business unit #s (5-digits) sitting in the AD Description location.

    1) I'd like to search ALL active users within a top level OU.

    get-aduser -ldapfilter "(&(&(samaccountname=b*)(useraccountcontrol=512)))"

    2) I want to get the "Description" property and save it's value (or put it into an array).

    3) I want to count the number of times that value is found across 1 or more users.

    4) Only values found are counted, so as it comes across the next user's BU, it either increments to an already found BU # or begins a new count for that new BU#.

    Wednesday, June 13, 2018 6:00 PM

Answers

  •  ....  -properties description | group description  


    • Marked as answer by NJTechNeck Thursday, June 14, 2018 3:49 PM
    Wednesday, June 13, 2018 7:20 PM
  • Thank you Mekac,

    I appended this to the end of my script (I accidentally mentioned description, but it is actually physicalDeliveryOfficeName).  Once changed, the output was what I needed, thank you very much.  I'm going to play with the output so I don't see all of the CN's listed as well.  

    FINAL script (all in one line)

    ---------------------

    get-aduser -searchbase "ou=sample,dc=domain,dc=com" -filter {enabled -eq $true} -properties phy
    sicalDeliveryOfficeName | group physicalDeliveryOfficeName

    ---------------------

    • Marked as answer by NJTechNeck Thursday, June 14, 2018 3:49 PM
    Thursday, June 14, 2018 3:49 PM

All replies

  • Hi All.  Thanks in advanced.

    I have business unit #s (5-digits) sitting in the AD Description location.

    1) I'd like to search ALL active users within a top level OU.

    get-aduser -ldapfilter "(&(&(samaccountname=b*)(useraccountcontrol=512)))"

    2) I want to get the "Description" property and save it's value (or put it into an array).

    3) I want to count the number of times that value is found across 1 or more users.

    4) Only values found are counted, so as it comes across the next user's BU, it either increments to an already found BU # or begins a new count for that new BU#.

    Use a hashtable to accumulate the numbers, using the contents of the user's description property as the key.

    Something like this:

    $bu = @{}
    get-aduser -ldapfilter "(&(&(samaccountname=b*)(useraccountcontrol=512)))" | ForEach {
    $bu[$_.Description] += 1
    }
    # dump the table
    $bu


    --- Rich Matheisen MCSE&I, Exchange Ex-MVP (16 years)

    Wednesday, June 13, 2018 6:40 PM
  •  ....  -properties description | group description  


    • Marked as answer by NJTechNeck Thursday, June 14, 2018 3:49 PM
    Wednesday, June 13, 2018 7:20 PM
  • I would use a PS5 class, a function, and some logic to do this :) it worked for me in a test

    Enjoyed doing this...

    #A CLASS
    class Description{
        [string]$number
        [int]$Frequency
        #default constructor
        Description(){
            $this.number = 00000
            $this.Frequency =0
        }
        #constructor with a number
        Description([string]$n){
            $this.number = $n
        }
        #constructor with a number and a frequency
        Description([string]$n,[int]$f){
            $this.number = $n
            $this.Frequency =$f
        }
    
        [Description]static Add([string]$number){
            #using constructor with number and frequency
            return New-Object Description -ArgumentList $number,1
        }
        [Description]static AddOne([string]$number,[Description]$desc){
            #adding one to the frequency on the $desc object
            $desc.Frequency++
            return $desc
        }
    }
    #function to check if the number is present in the $global:Frequency
    function Is-NumberPresent{
        [CmdletBinding()]
        param(
            [Parameter(Position=0,Mandatory=$true)]$number,
            [Parameter(Position=1,Mandatory=$true)]$Array
        )
        begin{
            [bool]$answer=$false
        }
        process{
            foreach($item in $Array.Number){
                if($item -eq $number){
                    $answer =$true
                    break;
                }
            }
        }
        end{
            return $answer
        }
    }
    
    #all numbers (strings with 5 digits)
    $AllNumbers=@()
    Get-ADUser -Filter 'enabled -eq $true' -Properties description | %{ if($_.description -match "\d{5}"){$AllNumbers+=$_.description} }
    #$AllNumbers=@("12345","12345","12345","54321","19371","69877")
    
    #definition of the output variable
    $Global:Frequency=@()
    #seach on each number
    foreach($number in $AllNumbers){
        #if number is not present, add it as new with frequency 1
        if(!(Is-NumberPresent $number $Global:Frequency)){
           $Global:Frequency+=[Description]::Add($number)
        }
        else{
            #Then exists, you need to find the object where the number is $number in the foreach
            $getdes = $Global:Frequency | select * | where {$_.number -eq $number}
            #since there are no Remove call, we need to create the object from scratch withot the information we just found
            [Array]$Global:Frequency = $Global:Frequency | where{ $_.number -ne $getdes.number}
    
            #so we can add it with the updated frequency
            [Array]$Global:Frequency+= [Description]::AddOne($number,$getdes)
        }
    }
    
    $Global:Frequency | ConvertTo-Json | Out-File ".\hystogram.json"


    • Proposed as answer by j0rt3g4 Thursday, June 14, 2018 7:01 AM
    • Edited by j0rt3g4 Thursday, June 14, 2018 7:07 AM
    Thursday, June 14, 2018 7:01 AM
  • Thank you, Rich.  I was comparing back and forth between the two methods to find an enabled user.  In both runs, I am receiving an error:

    _____________________

    Import-Module ActiveDirectory
    $bu = @{}
    get-aduser -searchbase "ou=sample,dc=domain,dc=com" -filter {enabled -eq $true} | ForEach {
    $bu[$_.Description] += 1
    }
    # dump the table
    $bu
    pause

    _____________________

    Index operation failed; the array index evaluated to null.
    At C:\Users\XXXXXX\AD_User_count - Copy.ps1:4 char:1
    + $bu[$_.Description] += 1
    + ~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
        + FullyQualifiedErrorId : NullArrayIndex

    Thursday, June 14, 2018 3:41 PM
  • j0rt3g4, 

    Thank you very much for your work.  From my little programming knowledge, I do not have json experience, so I am currently leaning towards a powershell method.   Greatly appreciate you taking the time on this.

    Best,

    NJTechNeck

    Thursday, June 14, 2018 3:43 PM
  • Thank you Mekac,

    I appended this to the end of my script (I accidentally mentioned description, but it is actually physicalDeliveryOfficeName).  Once changed, the output was what I needed, thank you very much.  I'm going to play with the output so I don't see all of the CN's listed as well.  

    FINAL script (all in one line)

    ---------------------

    get-aduser -searchbase "ou=sample,dc=domain,dc=com" -filter {enabled -eq $true} -properties phy
    sicalDeliveryOfficeName | group physicalDeliveryOfficeName

    ---------------------

    • Marked as answer by NJTechNeck Thursday, June 14, 2018 3:49 PM
    Thursday, June 14, 2018 3:49 PM