{"id":63983,"date":"2007-09-20T02:13:00","date_gmt":"2007-09-20T02:13:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2007\/09\/20\/how-can-i-count-the-number-of-users-in-a-group\/"},"modified":"2007-09-20T02:13:00","modified_gmt":"2007-09-20T02:13:00","slug":"how-can-i-count-the-number-of-users-in-a-group","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-count-the-number-of-users-in-a-group\/","title":{"rendered":"How Can I Count the Number of Users in a Group?"},"content":{"rendered":"<p><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> \n<P>Hey, Scripting Guy! How can I count the number of users in an Active Directory group?<BR><BR>&#8212; TP<\/P><IMG height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" height=\"288\" alt=\"Script Center\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" align=\"right\" border=\"0\"><\/A> \n<P>Hey, TP. You know, it\u2019s our sad duty to confirm that the reports currently sweeping the Internet are true. Without wishing to alarm anyone, we must admit that one of the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/funzone\/bobbles.mspx\"><B>Around the World With Dr. Scripto Bobblehead<\/B><\/A> pictures appears to be a fake! (And no, we\u2019re not talking about the obvious one at the end.)<\/P>\n<P>Please, please; there\u2019s no need to panic. The Scripting Guys are working closely with representatives of the World Health Organization and we are confident that this fake picture poses no health hazard of any kind. (Although doctors <I>do<\/I> recommend that pregnant women and those with weak hearts stay away from the Script Center until the this issue has been resolved.) In addition, you can rest assured that the safety and well-being of Script Center users remains our highest priority: if the situation begins to get even <I>slightly<\/I> out of control we will shut down the Script Center and quarantine the Scripting Guys immediately.<\/P>\n<P>Which, come to think of it, is the very thing our manager recommends each time we meet with him.<\/P>\n<P>We should hasten to add that, at this point in time, we do not know for sure that one of the pictures is a fake; we currently have a team of forensic scientists and art experts examining all the evidence. Obviously this is a very serious matter, and we do not want to make any hasty accusations. Because of that, our investigation will take some time to complete. But trust us: we <I>will<\/I> get to the bottom of this.<\/P>\n<P>And what will we do if we discover that one of the pictures <I>is<\/I> a fake? To be honest, we haven\u2019t reached a consensus on that; however, Scripting Guy Jean Ross is currently standing by with a team of highly-trained commandos, ready to parachute into action on a moment\u2019s notice. But, then again, Scripting Guy Jean Ross is <I>always<\/I> ready to parachute into action at a moment\u2019s notice:<\/P>\n<P>\u201cSomeone has a question about text files? My team and I will parachute in.\u201d<\/P>\n<P>\u201cThere\u2019s a missing period in one of the <I>Sesame Script<\/I> articles? My team and I will parachute in.\u201d<\/P>\n<P>\u201cSomeone brought doughnuts and left them in the kitchen? My team and I will parachute in.\u201d<\/P>\n<TABLE class=\"dataTable\" id=\"E6D\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\"><B>Note<\/B>. Shouldn\u2019t someone talk to her about this erratic behavior? You bet they should. On the other hand, she\u2019s continually surrounded by a team of highly-trained commandos. <I>You<\/I> go tell her she\u2019s acting crazy!<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Needless to say, we will keep you informed as more information becomes available. In the meantime, we would like to show you a script that can count the number of users in an Active Directory group. And don\u2019t worry: this script comes with the <B>Scripting Guys Certificate of Authenticity<\/B>, ensuring that it is a <I>real<\/I> Scripting Guys script and not a fake.<\/P>\n<P>If it doesn\u2019t say Scripting Guys on it, you don\u2019t know what\u2019s inside.<\/P>\n<P>Here\u2019s the script:<\/P><PRE class=\"codeSample\">Set objGroup = GetObject(&#8220;LDAP:\/\/CN=Finance Employees,OU=Finance,DC=fabrikam,DC=com&#8221;)<\/p>\n<p>i = 0<\/p>\n<p>Set objDictionary = CreateObject(&#8220;Scripting.Dictionary&#8221;)<\/p>\n<p>For Each strUser in objGroup.Member\n    i = i + 1<\/p>\n<p>    Set objMember = GetObject(&#8220;LDAP:\/\/&#8221; &amp; strUser)\n    strType = objMember.Class<\/p>\n<p>    If Not objDictionary.Exists(strType) Then\n        objDictionary.Add strType, &#8220;1&#8221;\n    Else\n        objDictionary.Item(strType) = objDictionary.Item(strType) + 1\n    End If\nNext<\/p>\n<p>Wscript.Echo &#8220;Total members in the group: &#8221; &amp; i\nWscript.Echo<\/p>\n<p>For Each objType in objDictionary\n    Wscript.Echo objType &amp; &#8220;: &#8221; &amp; objDictionary.Item(objType)\nNext\n<\/PRE>\n<P>Two things we should note before we go much further. First, the only way to determine the number of members in a group is to go ahead and count those members; ADSI doesn\u2019t have a Count property that can instantly return the number of items in a collection for us. (Or at least it doesn\u2019t have a Count property that actually works.)<\/P>\n<P>Second, we could have written a simpler version of this script, one that looks like this:<\/P><PRE class=\"codeSample\">Set objGroup = GetObject(&#8220;LDAP:\/\/CN=Finance Employees,OU=Finance,DC=fabrikam,DC=com&#8221;)<\/p>\n<p>i = 0<\/p>\n<p>For Each strUser in objGroup.Member\n    i = i + 1\nNext<\/p>\n<p>Wscript.Echo &#8220;Total members in the group: &#8221; &amp; i\nWscript.Echo\n<\/PRE>\n<P>The preceding script does, indeed, echo back the number of members in a group. So why didn\u2019t we just give you that script and call it good? Well, in light of the controversy surrounding the doctored photo, we decided to go the extra step and echo back not only the number of members in a group, but also a tally of the <I>type<\/I> of group member, like so:<\/P><PRE class=\"codeSample\">Total members in the group: 840<\/p>\n<p>group: 5\ncontact: 595\nuser: 240\n<\/PRE>\n<P>That\u2019s just our way of trying to make amends for all the heartache and heartbreak that has no doubt accompanied the doctored photo scandal. Use whichever script best suits your needs, and with our compliments.<\/P>\n<P>As for the <I>original<\/I> script (the fancy one), that one kicks off by connecting to the group in question, in this case a group named Finance Employees, housed in the Finance OU of fabrikam.com:<\/P><PRE class=\"codeSample\">Set objGroup = GetObject(&#8220;LDAP:\/\/CN=Finance Employees,OU=Finance,DC=fabrikam,DC=com&#8221;)\n<\/PRE>\n<P>After we make a connection to the group account in Active Directory, we set the value of a counter variable named i to 1; we\u2019ll use this variable to tally the number of members in the group. From there we then create an instance of the <B>Scripting.Dictionary<\/B> object, the object we\u2019ll use to keep track of the different member types (like user, contact, and group):<\/P><PRE class=\"codeSample\">Set objDictionary = CreateObject(&#8220;Scripting.Dictionary&#8221;)\n<\/PRE>\n<P>That brings us to this line of code:<\/P><PRE class=\"codeSample\">For Each strUser in objGroup.Member\n<\/PRE>\n<P>As it turns out, Active Directory groups all have a multi-valued property named <B>Member<\/B>; this property contains a collection of all the members of that group. In order to get at the group membership all we have to do is set up a For Each loop to loop through all the values stored in the Member property.<\/P>\n<P>Which, coincidentally enough, is exactly what we did in our script.<\/P>\n<P>Inside the loop the first thing we do is increment the value of our counter variable. Each time we go through the loop we increment the value of i. Why? Well, suppose we have 37 members in the group. In that case, we\u2019re going to run through the loop 37 times; when we exit the loop, i will be equal to 37. Which, now that we think about it, means that i will thus be able to tell us how many members are in the group.<\/P>\n<P>Was that lucky or what?<\/P>\n<P>As you may or may not know, individual group members are listed in the Member attribute by distinguished name (e.g., CN= Ken Myer, OU=Finance, dc=fabrikam, dc=com). Is that useful? You bet it is; that means we can bind to the individual member account using the following line of code:<\/P><PRE class=\"codeSample\">Set objMember = GetObject(&#8220;LDAP:\/\/&#8221; &amp; strUser)\n<\/PRE>\n<P>Why do we even <I>want<\/I> to bind to the individual member account? Well, in addition to keeping a simple tally of the number of members in the group, we want to determine the member type; the only way to do that is to bind to the account and retrieve the value of the <B>Class<\/B> property. That\u2019s what we do here:<\/P><PRE class=\"codeSample\">strType = objMember.Class\n<\/PRE>\n<P>At this point we know that the group member is a user (or a contact or a group or whatever). But now what? Well, as we noted, we\u2019re going to use our Dictionary object to keep a running tally of member types. With that in mind, our next step is to check and see whether this particular member type is already in the Dictionary:<\/P><PRE class=\"codeSample\">If Not objDictionary.Exists(strType) Then\n<\/PRE>\n<P>Suppose the preceding line of code comes back True; that means the member type is <I>not<\/I> in the Dictionary. (Notice the <B>If Not<\/B> syntax.) In that case, we use the following line of code to add the type to the Dictionary and set the value of the new item to 1:<\/P><PRE class=\"codeSample\">objDictionary.Add strType, &#8220;1&#8221;\n<\/PRE>\n<P>Got that? If not, you might want to take a look at the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/guide\/sas_scr_ildk.mspx\"><B>Microsoft Windows 2000 Scripting Guide<\/B><\/A> for a more detailed look at the Dictionary object.<\/P>\n<P>But what if the member type <I>can<\/I> be found in the Dictionary? That\u2019s fine; if the member type already exists in the Dictionary then we simply use this line of code to increment the item value by 1:<\/P><PRE class=\"codeSample\">objDictionary.Item(strType) = objDictionary.Item(strType) + 1\n<\/PRE>\n<P>And then we loop around and repeat the process for the next member in the group.<\/P>\n<P>After we\u2019ve looped through the entire group membership we echo back the total number of members in the group (represented by our counter variable i), followed by a blank line:<\/P><PRE class=\"codeSample\">Wscript.Echo &#8220;Total members in the group: &#8221; &amp; i\nWscript.Echo\n<\/PRE>\n<P>And then we set up a For Each loop to loop through all the items in the Dictionary, echoing back the member type and the item value:<\/P><PRE class=\"codeSample\">For Each objType in objDictionary\n    Wscript.Echo objType &amp; &#8220;: &#8221; &amp; objDictionary.Item(objType)\nNext\n<\/PRE>\n<P>And that, as you might expect, is that.<\/P>\n<P>Oh, one more thing: if you\u2019d like to count the number of members in a local group, use this script instead:<\/P><PRE class=\"codeSample\">strComputer = &#8220;atl-fs-01&#8221;<\/p>\n<p>i = 0<\/p>\n<p>Set objGroup = GetObject(&#8220;WinNT:\/\/&#8221; &amp; strComputer &amp; &#8220;\/Administrators&#8221;)<\/p>\n<p>For Each strMember in objGroup.Members\n    i = i + 1\nNext<\/p>\n<p>Wscript.Echo &#8220;Total members in the group: &#8221; &amp; i\n<\/PRE>\n<P>We won\u2019t bother explaining how this script works, at least not today. But that\u2019s OK; we have <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/local.mspx\"><B>other sources of information<\/B><\/A> that explain how to work with local groups.<\/P>\n<P>Which brings us back around to the burning question of the day: are the Scripting Guys upset that someone submitted a doctored photo for publication in the Script Center? Well, to be honest, when it was pointed out to us, we thought it was kind of funny. (And, truth be told, it\u2019s <I>possible<\/I> that we might have used a <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/slides\/start.mspx\"><B>doctored photo or two<\/B><\/A> ourselves.) So no, we\u2019re not upset: if you want to take the trouble to create a doctored photo of Dr. Scripto, well, who are we to stop you? <\/P>\n<P>Besides, there are even unsubstantiated rumors that Dr. Scripto himself isn\u2019t real, that he\u2019s just a piece of clip art. Is there any truth to those rumors? We don\u2019t know. But you can bet that Jean Ross and her Delta Scripting Force will find out.<\/P>\n<P>Just as soon as they finish those doughnuts they liberated from the kitchen.<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I count the number of users in an Active Directory group?&#8212; TP Hey, TP. You know, it\u2019s our sad duty to confirm that the reports currently sweeping the Internet are true. Without wishing to alarm anyone, we must admit that one of the Around the World With Dr. Scripto Bobblehead [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[7,44,3,20,5],"class_list":["post-63983","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-active-directory","tag-groups","tag-scripting-guy","tag-user-accounts","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I count the number of users in an Active Directory group?&#8212; TP Hey, TP. You know, it\u2019s our sad duty to confirm that the reports currently sweeping the Internet are true. Without wishing to alarm anyone, we must admit that one of the Around the World With Dr. Scripto Bobblehead [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/63983","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=63983"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/63983\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=63983"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=63983"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=63983"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}