none
VBScript problem with WINNT object only returning 100 users from Active Directory RRS feed

  • Question

  • I have this problem that just recently started happening.  I've created this snippet that isolates the problem, which is basically, the same VBScript that used to return all of my users from Active Directory, now only returns the first 100 users.  If I filter by group, then i get all of the groups (which is more than 100).  The problem started happening last November, then went away for a while and has come back.  The server guys tell me that nothing should have changed there.  Can anyone give me some advice on what might be causing this?

    When I run this script for various domains, i get a numbered list of just the first 100 users.  I'm running this on IIS (which hasn't changed)

    sub PullAllUsers(strDomain)
     Dim iCount
     Dim object
     Dim objDomain
     Set objDomain = getobject("WinNT://" & strDomain)
     objDomain.filter = Array("user")
     iCount = 0
     For each object in objDomain
    	iCount = iCount + 1
    	Response.Write CStr(iCount) + " - " + object.Name + " "
     Next
    End Sub 
    Wednesday, March 16, 2011 12:06 PM

Answers

  • True, AD Contact objects do not have a sAMAccountName attribute. I was thinking possibly the script Thiyagu14 posted raised an error because the Where clause would retrieve users and contacts. However, my testing indicates the script does not raise an error, even on contact objects. That leaves no explanation for any problems with the script using the LDAP provider. And there is no explanation for the script using the WinNT provider being limited to 100 names. In that case, there is no paging or any other limitation. It should be able to list many 1000's of users (although it could be slow). The only explanation must be an IIS limitation, either a timeout or record size limitation of some kind.

     


    Richard Mueller - MVP Directory Services
    Thursday, March 24, 2011 9:24 PM
    Moderator

All replies

  • I suspect something in IIS accounts for this. If you run the script from a command prompt, using Wscript.Echo instead of Response.Write, and call the Sub with the name of your domain, it should run fine.

     


    Richard Mueller - MVP Directory Services
    Wednesday, March 16, 2011 12:27 PM
    Moderator
  • why not use it like this, which have a nice option of setting page size

    On Error Resume Next
    Const ADS_SCOPE_SUBTREE = 2
    Set objConnection = CreateObject("ADODB.Connection")
    Set objCommand = CreateObject("ADODB.Command")
    objConnection.Provider = ("ADsDSOObject")
    objConnection.Open "Active Directory Provider"
    objCommand.ActiveConnection = objConnection
    objCommand.Properties("Page Size") = 1000 
    objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 
    objCommand.Properties("Cache Results") = False 
    objCommand.CommandText = _ "SELECT cn,samaccountname,adspath FROM 'LDAP://DC=mydomain,DC=com'" _ & " WHERE objectCategory = 'user'"
    Set objRecordSet = objCommand.Execute
    objRecordSet.MoveFirst 
    Do Until objRecordSet.EOF 
    Wscript.Echo objRecordSet.Fields("samaccountname").Value 
    objRecordSet.MoveNext 
    Loop 
    
    
    

    -join("74686979616775313440686F746D61696C2E636F6D"-split"(?<=\G.{2})",21|%{[char][int]"0x$_"})
    http://www.myExchangeWorld.com
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Wednesday, March 16, 2011 12:30 PM
    Moderator
  • Thanks.  I tried this, but i get

    Provider error '80004005' 
    Unspecified error 

    When it tries to do the  objCommand.Execute.  

    I've tried LDAP in the past, and the problem seems to be that i can't get the SAMAccountName.  If I remove that from the SELECT statement, then yes, I get all of my users.  By the way, in this scenario, the Page Size doesn't seem to come into the picture.  Even set at 1000, I get 5000+ returns.

    My problem is that I need the SAMAccountName, which I get with the method described in the original problem above... but obviously there I am only getting 100 users right now.  I have looked for page parameters for the WINNT Object, but can not find any.  Any suggestions on 1) how to get the SAMAccountName from LDAP? or 2) how to get more than 100 users? (or why it suddenly started limiting me?)

    Thanks!!

    Steve

    Wednesday, March 16, 2011 1:08 PM
  • script about should work, did u change the ldap string to ur own domain name?

    comment the first line (put a ' infront of the line)

    and let us know where the script errors out, and give that line here.


    -join("74686979616775313440686F746D61696C2E636F6D"-split"(?<=\G.{2})",21|%{[char][int]"0x$_"})
    http://www.myExchangeWorld.com
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Wednesday, March 16, 2011 1:09 PM
    Moderator
  • If I do need to run this from a web site, would this mean that IIS will need to be fixed?  I'll have the server folks try it from the command line, but do you know what in IIS I can point them at to look at?  Thanks for your help!
    Wednesday, March 16, 2011 1:11 PM
  • I changed the LDAP string to my own domain and had commented out the ON ERROR line.

    The error occurs on:

    Set objRecordSet = objCommand.Execute

    line.

    If I change the previous line to

    objCommand.CommandText = _ "SELECT cn,adspath FROM 'LDAP://DC=mydomain,DC=com'" _ & " WHERE objectCategory = 'user'"
    

    (of course, with my correct domain), then I do not get an error and DO get all of the users.  For some reason, it won't recognize SAMAccountName.

    Steve

    Wednesday, March 16, 2011 1:17 PM
  • you have to change the select statement

    include samaccountname in the select statement like this:

    'select samaccountname,cn"

    and give it a try


    -join("74686979616775313440686F746D61696C2E636F6D"-split"(?<=\G.{2})",21|%{[char][int]"0x$_"})
    http://www.myExchangeWorld.com
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Wednesday, March 16, 2011 1:19 PM
    Moderator
  • Whenever I add samaccountname to the select statement (I just tried 'select samaccountname,cn'), then when the
    Set objRecordSet = objCommand.Execute

    line tries to execute, it gives the following error:

    Provider error '80004005' 
    Unspecified error 
    Steve
    Wednesday, March 16, 2011 1:24 PM
  • First, remove the "On Error Resume Next". Second, the problem might be the WHERE clause

    WHERE objectCategory = 'user'

     

    which retrieves both user and contact objects. Contact objects do not have a sAMAccountName attribute. Change the WHERE clause to:

    WHERE objectCategory = 'person' AND objectClass = 'user'

     

    Next, you can assign any value to "Page Size" up to 1000. The actual number is not important because any non-zero value turns on paging. A "Page Size" of 100 means rows are retrieved 100 at a time until all are retrieved, no matter how many there are. If there is no "Page Size", the limit is 1000 in AD 2000 and 1500 in AD 2003 and above. There is no "Page Size" involved in your WinNT example. There also would be no "Page Size" if you used the LDAP provider in a similar way to enumerate all users in an OU. It is ADO that has a "Page Size", not LDAP or WinNT.

    There should be no problem with your code that uses the WinNT provider (except it will be slower). The Name property returns the Relative Distinguished Name of the AD object no matter the class, and your code should ignore contacts. I still think some IIS setting must account for the problems with your code using WinNT. It works in my test domain with over 2000 users. I would expect code using ADO to work if paging is turned on.

     


    Richard Mueller - MVP Directory Services
    Wednesday, March 16, 2011 2:48 PM
    Moderator
  • I was wrong. I just ran a script very similar to that suggested by Thiyagu14, using "WHERE objectCategory = 'user'" and retrieving sAMAccountName (the underscores, "_", in the CommandText should be removed). It indeed did retrieve all users and contacts. It's just that the sAMAccountName's of the contacts was missing. No error was raised by the Execute method. Something else must be wrong if you can retrieve cn but not sAMAccountName, but I cannot imagine what.

     


    Richard Mueller - MVP Directory Services
    Wednesday, March 16, 2011 3:00 PM
    Moderator
  • I suspect something in IIS accounts for this. If you run the script from a command prompt, using Wscript.Echo instead of Response.Write, and call the Sub with the name of your domain, it should run fine.

     


    Richard Mueller - MVP Directory Services

    I had the server folks run the script (with output modifications) on the server from the command line, and as you suspected, it ran fine.  I've pointed them at IIS and perhaps there will be something the IIS logs.  Any suggestions on where else to look or what could possibly cause this?
    Wednesday, March 16, 2011 6:29 PM
  • It's just that the sAMAccountName's of the contacts was missing.

    I don't think contacts have a sAMAccountName attribute.

    Bill

    Thursday, March 24, 2011 7:58 PM
    Moderator
  • True, AD Contact objects do not have a sAMAccountName attribute. I was thinking possibly the script Thiyagu14 posted raised an error because the Where clause would retrieve users and contacts. However, my testing indicates the script does not raise an error, even on contact objects. That leaves no explanation for any problems with the script using the LDAP provider. And there is no explanation for the script using the WinNT provider being limited to 100 names. In that case, there is no paging or any other limitation. It should be able to list many 1000's of users (although it could be slow). The only explanation must be an IIS limitation, either a timeout or record size limitation of some kind.

     


    Richard Mueller - MVP Directory Services
    Thursday, March 24, 2011 9:24 PM
    Moderator
  • We have the same problem in Windows 2019.  I have two DCs, one 2019 and one 2016.  If I point to the 2016 DC, all users (2,000+) are returned.  If I point to the 2019 server, only the first 100 alphabetically are returned.  This is not an IIS problem.  Any ideas?

    Thursday, June 13, 2019 3:33 PM
  • Interesting. A script that works on Windows Server 2016, but fails on Windows Server 2019, reminds me of a problem with memory discussed in this thread:

    https://social.technet.microsoft.com/Forums/en-US/4f14412f-dd81-4b9a-b6b5-aa69100e87d0/intermittent-not-enough-space-errors-when-doing-ldap-queries-against-2019-domain-controller?forum=winservergen

    However, the problem is this thread happens when users employ the LDAP_MATCHING_RULE_IN_CHAIN in an LDAP syntax filter. For example, using dsquery to find all members of a group:

    dsquery * -Filter "(memberOf:1.2.840.113556.1.4.1941:= 
    cn=Test,ou=East,dc=Domain,dc=com)"

    This is an extended match operator that walks the chain of ancestry in objects all the way to the root until it finds a match. This reveals group nesting.

    But the WinNT provider does not support the LDAP syntax. WinNT supports a flat namespace. It is blind to the hierarchy of Active Directory. A WinNT query for users cannot be converted into an LDAP query using LDAP_MATCHING_RULE_IN_CHAIN.

    The issue discussed in the thread I linked has been identified by Microsoft as an "LDAP memory arena" issue. The fix is not expected until September. I wonder if the memory problem could possibly cause WinNT to only retrieve 100 users.

    I posted in the thread I linked to ask if the identified problem could possibly account for WinNT only retrieving 100 users.

    It would help if you post the code you use to retrieve users using WinNT.


    Richard Mueller - MVP Enterprise Mobility (Identity and Access)

    Thursday, June 13, 2019 6:17 PM
    Moderator
  • Here's the code: (a simple query)

      Set dom = GetObject("WinNT://DC")  ' where DC = name of domain controller. If set to a win2016 OR earlier DC, it works great.  It only shows first 100 users if pointed to a win2019 DC.

    dom.Filter = Array("user")

      For each usr in dom
      Next

    Monday, June 17, 2019 11:41 AM
  • Chiming in, we have *just* started to have this issue yesterday quering computers accounts running some sysmgmt scripts used for many years. We run only W2K16 DCs (4 in this AD site) and a variarity of OS' on member servers. So *no* W2K19 involved.

    Tested from W2K3 (only one in a corner, so don't shoot me), W2K8R2, W2K12R2, W2K16 and we get random results pointing to the DC getting queried.

    I have no luck substituting the domain name with the name of a DC (returns nothing).

    Test code used for troubleshooting:

    strDomain = "domain.com" Set objDomain = GetObject("WinNT://" & strDomain) objDomain.Filter = Array("computer")

    For Each objComputer In objDomain intTotalServers = intTotalServers + 1 strComputer = objComputer.Name Next WScript.Echo intTotalServers & " accounts found"



    Friday, July 12, 2019 6:17 AM
  • 1 of the 4 DC's in the AD site was updated yesterday morning with these patches:

    2019-07 Servicing Stack Update for Windows Server 2016 for x64-based Systems (KB4509091)
    2019-07 Cumulative Update for Windows Server 2016 for x64-based Systems (KB4507460)
    Windows Malicious Software Removal Tool x64 - July 2019 (KB890830)

    I obv. can't shut down or uninstall during daytimes, so is reduced to testing by script or tools.

    As it doesn't work pointing the code straight to a DC (should it?), any ideas on other ways to target a specific DC until I can test by shutting down the updated DC or removing the latest updates as a test?


    Friday, July 12, 2019 6:26 AM
  • You should be able to target a specific DC as follows:

    strDomain = "domain"
    strDC = "MyDC"
    Set objDomain = GetObject("WinNT://" & strDC & "/" & strDomain)

    I use just the NetBIOS name of the domain.


    Richard Mueller - MVP Enterprise Mobility (Identity and Access)

    Friday, July 12, 2019 10:29 AM
    Moderator