{"id":69993,"date":"2005-04-19T16:38:00","date_gmt":"2005-04-19T16:38:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2005\/04\/19\/how-can-i-tell-whether-a-group-member-is-a-user-a-computer-or-another-group\/"},"modified":"2005-04-19T16:38:00","modified_gmt":"2005-04-19T16:38:00","slug":"how-can-i-tell-whether-a-group-member-is-a-user-a-computer-or-another-group","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-tell-whether-a-group-member-is-a-user-a-computer-or-another-group\/","title":{"rendered":"How Can I Tell Whether a Group Member is a User, a Computer, or Another Group?"},"content":{"rendered":"<p><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"> \n<P>Hey, Scripting Guy! How can I tell whether the member of a group is a user, a computer, or another group?<BR><BR>&#8212; ON<\/P><IMG border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" border=\"0\" alt=\"Script Center\" align=\"right\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" height=\"288\"><\/A> \n<P>Hey, ON. Interesting question and &#8211; to tell you the truth &#8211; one we\u2019d never really thought about. It\u2019s easy enough to list all the members of a group; for example, here\u2019s a script that reports back all the members of the Finance Managers group:<\/P><PRE class=\"codeSample\">Set objGroup = GetObject _\n    (&#8220;LDAP:\/\/cn=Finance Managers, ou=Finance, dc=fabrikam, dc=com&#8221;)<\/p>\n<p>For Each strUser on objGroup.Member\n        Wscript.Echo strUser\nNext\n<\/PRE>\n<P>When you run this script you\u2019ll get back the value of the <B>distinguishedName<\/B> (DN) attribute for each member of the group; that output will look something like this:<\/P><PRE class=\"codeSample\">cn=atl-ws-01, ou=Finance, dc=fabrikam, dc=com\ncn=Ken Myer, ou=Finance, dc=fabrikam, dc=com\ncn=North American Finance Users, ou=Finance, dc=fabrikam, dc=com\ncn=Pilar Ackerman, ou=Finance, dc=fabrikam, dc=com\n<\/PRE>\n<P>So what\u2019s wrong with that? Well, nothing, except that &#8211; depending on your naming conventions &#8211; it might be difficult to look at the list and determine whether a group member is a user, a computer, or even another group. Likewise, your script might be designed to take specific action based on the item type; for example, if a group member happens to be another group you might want to use a recursive function to connect to and list the members of <I>that<\/I> group. But you can\u2019t do that unless you can first determine whether or not the member actually <I>is<\/I> another group.<\/P>\n<P>So how can we distinguish users from computers and groups from whatever? As it turns out all Active Directory objects have an attribute named <B>Class<\/B>. (Yes, in Active Directory even the Scripting Guys have Class!) The Class attribute can tell you what kind of object you\u2019re dealing with: a user, a computer, a group, whatever. To tell the difference all you have to do is examine the value of the Class attribute.<\/P>\n<P>Of course, there <I>is<\/I> one tiny catch. When you enumerate group members the only attribute you get back is the member\u2019s distinguished name; you don\u2019t get back the Class attribute. That means you can\u2019t just enumerate group members and their Class types. Instead, you need to bind to each individual group member\u2019s Active Directory account and <I>then<\/I> echo back the value of the Class attribute. But don\u2019t worry; that\u2019s very easy. <\/P>\n<P>Let\u2019s take a look at a script that reports back group membership and Class types for the Finance Managers group: <\/P><PRE class=\"codeSample\">Set objGroup = GetObject _\n    (&#8220;LDAP:\/\/cn=Finance Managers, ou=Finance, dc=fabrikam, dc=com&#8221;)<\/p>\n<p>For Each strUser on objGroup.Member\n    Set objMember = GetObject(&#8220;LDAP:\/\/&#8221; &amp; strUser)\n    Wscript.Echo objMember.CN &amp; &#8220;, &#8221; &amp; objMember.Class\nNext\n<\/PRE>\n<P>What did we tell you: just a few lines of code and we\u2019re done. We begin by binding to the Finance Managers group in Active Directory. After making the connection we use a simple For Each loop to loop through all the values in the multi-valued attribute <B>Member<\/B>. Because Member just happens to contain the distinguished names of all the members of the group, looping through these values will\u2026well, give us the distinguished names of all the members of the group.<\/P>\n<P>And before you ask, yes, the attribute name probably <I>should<\/I> be Members, with an <I>s<\/I> on the end. But it\u2019s not; go figure.<\/P>\n<P>Now, if all we wanted was the DN for each group member we\u2019d be done. However, we need to get the value of the Class attribute as well. Therefore, inside our For Each loop we bind to the Active Directory account of each group member. That\u2019s what we do with this line of code:<\/P><PRE class=\"codeSample\">Set objMember = GetObject(&#8220;LDAP:\/\/&#8221; &amp; strUser)\n<\/PRE>\n<P>To bind to an Active Directory object you need to specify the object\u2019s ADsPath. The ADsPath consists of the ADSI provider name (for Active Directory that will always be <B>LDAP:\/\/<\/B>) followed by the object\u2019s distinguished name. We already have the DN; that\u2019s stored in the variable strUser. Consequently, all we have to do is concatenate <B>LDAP:\/\/<\/B> with the value of strUser, and pass that value to the <B>GetObject<\/B> method. In turn, GetObject will bind us to the Active Directory account.<\/P>\n<P>Make sense? Good.<\/P>\n<P>After we\u2019re connected to the account we can echo back the values of any attributes belonging to that account. In our sample script we simply echo back the value of the <B>CN<\/B> and Class attributes (with a comma to separate them); that gives us output similar to this:<\/P><PRE class=\"codeSample\">atl-ws-01, computer\nKen Myer, user\nNorth American Finance Users, group\nPilar Ackerman, user\n<\/PRE>\n<P>There you have it: output that distinguishes between classes such as users, computers, and groups. No one ever believes us when we say a scripting task is easy, but this time we have <I>proof<\/I>!<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I tell whether the member of a group is a user, a computer, or another group?&#8212; ON Hey, ON. Interesting question and &#8211; to tell you the truth &#8211; one we\u2019d never really thought about. It\u2019s easy enough to list all the members of a group; for example, here\u2019s a [&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-69993","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 tell whether the member of a group is a user, a computer, or another group?&#8212; ON Hey, ON. Interesting question and &#8211; to tell you the truth &#8211; one we\u2019d never really thought about. It\u2019s easy enough to list all the members of a group; for example, here\u2019s a [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/69993","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=69993"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/69993\/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=69993"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=69993"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=69993"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}