Kaseya Community

Count AD User accounts

  • Hi,

    I'd like to find a script (I assume it would need to involve VB scripting) that can query AD, and count the number of user accounts and then write that figure to a text file. From there I can pick it up with Kaseya and raise an alarm if its higher than a certain threshold. This is to ensure my managed Services customers are compliant with their Windows licensing requirements.

    Thanks in advance...
    David

    Legacy Forum Name: Count AD User accounts,
    Legacy Posted By Username: Zynet
  • Here's a VBS script we wrote to parse the number of users in a group. We use it to audit SPLA licenses... I think this will help you. You can pass the name of the group on the command line line:

    cscript enum_users.vbs Administrators

    You can probably hack around with it an make it better. Share it back if you do!


    option explicit

    dim strComputer, objWMIService, colItems, objItem, isDC, onDomain
    Dim adoCommand, adoConnection, strBase, strFilter, strAttributes
    Dim objRootDSE, strDNSDomain, strQuery, adoRecordset
    Dim objGroup, strDN, dicSeenGroupMember, count
    dim strGroup, colGroups, objUser, objArgs, objMember
    dim level, subtotal

    Const adCmdText = &H0001
    Const adUseClient = 3

    'check whether running on a DC
    strComputer = "."
    Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
    Set colItems = objWMIService.ExecQuery("Select DomainRole from Win32_ComputerSystem",,48)
    For Each objItem in colItems

    if objItem.DomainRole = 4 or objItem.DomainRole = 5 then
    isDC = true
    onDomain = true
    end if
    if objItem.DomainRole = 1 or objItem.DomainRole = 3 then
    onDomain = true
    end if

    Wscript.Echo "DomainRole: " & objItem.DomainRole
    '0 Standalone Workstation
    '1 Member Workstation
    '2 Standalone Server
    '3 Member Server
    '4 Backup Domain Controller
    '5 Primary Domain Controller

    Next
    'if not isDC then wscript.echo "Not running on a DC."
    'wscript.quit 1

    'command line args
    set objArgs = WScript.Arguments
    if objArgs.Count <> 1 then
    strGroup = "Administrators"
    else
    strGroup = objArgs.Item(0)
    end if

    'use a dictionary object to check for dups
    set dicSeenGroupMember = CreateObject("Scripting.Dictionary")

    if onDomain then

    ' Setup ADO objects.
    Set adoRecordset = CreateObject("ADODB.Recordset")
    Set adoConnection = CreateObject("ADODB.Connection")
    adoConnection.Provider = "ADsDSOObject"
    adoConnection.Open "Active Directory Provider"

    ' Search entire Active Directory domain.
    Set objRootDSE = GetObject("LDAP://RootDSE")
    strDNSDomain = objRootDSE.Get("defaultNamingContext")
    strBase = ""

    ' Filter on object with matching group name. Use * on cmd line makes it LIKE.
    strFilter = "(&(objectCategory=group)(name=domain users*))"

    ' Comma delimited list of attribute values to retrieve.
    strAttributes = "distinguishedName"

    ' Construct the LDAP syntax query.
    strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
    wscript.echo "Query: " & strQuery
    adoRecordset.CursorLocation = adUseClient
    adoRecordset.Sort = "distinguishedname"
    ' Run the query.
    adoRecordset.Open strQuery, adoConnection, , , adCmdText

    ' Enumerate the resulting recordset.
    Do Until adoRecordset.EOF
    ' Retrieve value.
    strDN = adoRecordset.Fields("distinguishedName").Value

    Wscript.Echo "Members of " & strDN & ":"
    DisplayMembers "LDAP://" & strDN, " ", dicSeenGroupMember, count, level, subtotal

    ' Move to the next record in the recordset.
    adoRecordset.MoveNext
    Loop

    ' Clean up.
    adoRecordset.Close
    adoConnection.Close
    wscript.echo "Total user count: " & count
    wscript.quit 0

    Function DisplayMembers (strGroupADsPath, strSpaces, dicSeenGroupMember, count, level, subtotal)

    level = level + 1

    'create AD item from AD path
    set objItem = GetObject(strGroupADsPath)

    'object is a group so it has members
    for each objMember In objItem.Members

    'if object is a group, call this routine recursively
    if objMember.Class = "group" then
    'display the name (attribute returned as field in query)
    Wscript.Echo strSpaces & objMember.Get("distinguishedname")
    DisplayMembers objMember.ADsPath, strSpaces & " ", dicSeenGroupMember, count, level, subtotal
    else
    'if object is not a group, check if it has ben counted yet and report
    'if dicSeenGroupMember.Exists(objMember.get("distinguishedname")) then
    ' Wscript.Echo strSpaces & objMember.Get("distinguishedname") & " ==> duplicate"
    'else
    Wscript.Echo strSpaces & objMember.Get("distinguishedname")
    'object not yet counted so add to collection and increment counter
    'dicSeenGroupMember.Add objMember.get("distinguishedname"), 1
    'count = count + 1
    'subtotal = subtotal + 1
    'end if
    end if
    next

    if level
    wscript.echo strSpaces & "Sub-Total user count for " & objItem.Get("distinguishedname") & ": " & subtotal
    wscript.echo ""
    wscript.echo ""
    subtotal = 0
    set dicSeenGroupMember = CreateObject("Scripting.Dictionary")
    end if
    level = level - 1

    End Function

    else
    dim bPartial

    'if machine is not on a domain, can't do LDAP query, just have to iterate the tree

    'check if partial match required
    if right(strGroup, 1) = "*" then
    bPartial = true
    strGroup = lcase(left(strGroup, len(strGroup) - 1))
    else
    strGroup = lcase(strGroup)
    bPartial = false
    end if

    'get the base security object
    Set colgroups = GetObject("WinNT://" & strComputer)

    'filter for groups
    colGroups.Filter = Array("group")

    For Each objgroup In colGroups

    if ((left(lcase(objgroup.name), len(strGroup)) = strGroup) and bPartial) or (lcase(objGroup.name) = strGroup) then

    'if group is a match, then display the members (local machine can't do nested groups)
    wscript.echo objGroup.adspath
    For Each objuser in objgroup.members

    if dicSeenGroupMember.Exists(objUser.adspath) then
    wscript.echo " " & objuser.adspath & " ==> duplicate"
    else
    wscript.echo " " & objuser.adspath
    'object not yet counted so add to collection and increment counter
    dicSeenGroupMember.Add objUser.adspath, 1
    count = count + 1
    end if
    Next
    end if
    Next

    wscript.echo "Total user count: " & count

    End If



    Legacy Forum Name: Scripts Forum,
    Legacy Posted By Username: dbennett
  • Thanks for the reply, however it didnt quite work for me for some reason.

    However I found a script that did. The URL is

    http://www.windowsadminscripts.com/coding/networking/adusers/

    Hope this helps...
    Dave

    Legacy Forum Name: Scripts Forum,
    Legacy Posted By Username: Zynet