{"id":55963,"date":"2008-03-20T00:20:00","date_gmt":"2008-03-20T00:20:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2008\/03\/20\/hey-scripting-guy-how-can-i-list-the-members-of-a-domain-group-that-belongs-to-the-local-administrators-group\/"},"modified":"2008-03-20T00:20:00","modified_gmt":"2008-03-20T00:20:00","slug":"hey-scripting-guy-how-can-i-list-the-members-of-a-domain-group-that-belongs-to-the-local-administrators-group","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-list-the-members-of-a-domain-group-that-belongs-to-the-local-administrators-group\/","title":{"rendered":"Hey, Scripting Guy! How Can I List the Members of a Domain Group That Belongs to the Local Administrators Group?"},"content":{"rendered":"<p><img decoding=\"async\" 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\" \/> <\/p>\n<p>Hey, Scripting Guy! I manage over 300 servers in our environment. For each server I need to determine the members of the local Administrators account. It\u2019s easy to get a list of local users and domain users that belong to the Admin account; it\u2019s also easy to get a list of any domain <i>groups<\/i> that belong to the Administrators account. However, what I\u2019d <i>really<\/i> like to do is take each of those domain groups and then get a list of <i>their<\/i> members. In other words, I don\u2019t want to know just that the Finance Managers group has local Administrator rights; I\u2019d like to know who belongs to the Finance Managers group (and thus has local Admin rights). Can you help?<\/p>\n<p>&#8212; EG<\/p>\n<p><img decoding=\"async\" border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\" \/><img decoding=\"async\" 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 decoding=\"async\" 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> <\/p>\n<p>Hey, EG. You know the Scripting Guy who writes this column is always on the lookout for weird stories. (Why? Well, for one thing, he figures that if he relates enough of these stories he might not look so weird himself.) Recently he read about a doozy of a story: a lady in Kansas who spent two years sitting on a toilet seat, refusing to get up and leave the bathroom.<\/p>\n<p>Actually, that\u2019s not the weird part. The weird part is that her boyfriend was well aware that this woman was sitting on the toilet seat refusing to get up; in fact, he brought her food and water everyday, and repeatedly urged her to come out of the bathroom. Not only that, but he was the one who eventually called the police and summoned help, albeit after two years. Why two years before he called for help? No one knows, although the Scripting Guy who writes this column can picture him warning his girlfriend, \u201cOK, that\u2019s fine. But if you don\u2019t come out of the bathroom in the next two years I\u2019m calling the police.\u201d And, sure enough, he did.<\/p>\n<p>&#8220;She is an adult; she made her own decision,&#8221; said the boyfriend. &#8220;I should have gotten help for her sooner; I admit that. But after a while, you kind of get used to it.&#8221;<\/p>\n<p>We\u2019ll have to take his word for that one. <\/p>\n<p>Of course, just because you <i>can<\/i> get used to something doesn\u2019t mean that you <i>have<\/i> to get used to something. For example, many of you have probably gotten used to the fact that, when you look at the members of the local Administrators group, all you can do is see that a domain group is one of the members; you can\u2019t actually see who\u2019s a member of that domain group. Over the years you\u2019ve come to accept that fact.<\/p>\n<p>The only problem is this: that isn\u2019t a fact after all. As it turns out, you <i>can<\/i> see who is a member of any domain group that belongs to a local Administrators group. And in today\u2019s column, we\u2019re going to show you exactly how to do that.<\/p>\n<p>Just as soon as the Scripting Guy who writes this column gets out of the bathroom.<\/p>\n<p>OK, here we go:<\/p>\n<pre class=\"codeSample\">strComputer = \"atl-fs-001\"\nstrTestString = \"\/\" &amp; strComputer &amp; \"\/\"\n\nSet objGroup = GetObject(\"WinNT:\/\/\" &amp; strComputer &amp; \"\/Administrators\")\n\nFor Each objMember In objGroup.Members\n    If objMember.Class = \"Group\" Then\n        If Not InStr(objMember.AdsPath, strTestString) Then\n            Set objDomainGroup = GetObject(objMember.AdsPath)\n            Wscript.Echo objDomainGroup.Name\n            For Each objDomainMember in objDomainGroup.Members\n                Wscript.Echo objDomainMember.FullName &amp; \" (\" &amp; objDomainMember.Name &amp; \")\"\n            Next\n            Wscript.Echo\n        End If\n    End If\nNext\n<\/pre>\n<p>So how does this script actually work? Well, let\u2019s see if we can figure that out. As you can see, we start out in pretty straightforward fashion; we simply assign the name of the computer in question (atl-fs-001) to a variable named strComputer:<\/p>\n<pre class=\"codeSample\">strComputer = \"atl-fs-001\"\n<\/pre>\n<p>Of course, after that promising beginning we then run smack-dab into <i>this<\/i> line of code:<\/p>\n<pre class=\"codeSample\">strTestString = \"\/\" &amp; strComputer &amp; \"\/\"\n<\/pre>\n<p>Good question: why in the world <i>did<\/i> we insert this weird line of code? Have the Scripting Guys become a little disoriented after spending two years in a bathroom?<\/p>\n<p>Of course not; the Scripting Guys don\u2019t need to spend two years in a bathroom just to become a little disoriented. Besides, as we noted in a <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/apr06\/hey0413.mspx\"><b>previous column<\/b><\/a>, there is no property that makes it a snap to distinguish between a local account and an Active Directory account. Instead, the only thing you can do is to look at the ADsPath for each account. A local account will always include the computer name as part of the property value; for example:<\/p>\n<pre class=\"codeSample\">WinNT:\/\/FABRIKAM\/atl-fs-01\/KenMyer\n<\/pre>\n<p>By contrast, a domain account will feature only the name of the domain (Fabrikam):<\/p>\n<pre class=\"codeSample\">WinNT:\/\/FABRIKAM\/KenMyer\n<\/pre>\n<p>Need to distinguish between a local account and a domain account? The easiest way that we know of to do this is to simply check to see if the computer name \u2013 enclosed in \/\u2019s \u2013 appears in the ADsPath. In our somewhat-cryptic line of code we\u2019re simply assigning the computer name \u2013 enclosed in \/\u2019s \u2013 to the variable strTestString. In other words, strTestString will be equal to this:<\/p>\n<pre class=\"codeSample\">\/atl-fs-001\/\n<\/pre>\n<p>Our next step is to bind to the Administrators group on the computer atl-fs-001; that\u2019s what this line of code is for:<\/p>\n<pre class=\"codeSample\">Set objGroup = GetObject(\"WinNT:\/\/\" &amp; strComputer &amp; \"\/Administrators\")\n<\/pre>\n<p>After we\u2019ve made the connection to the local Administrators group we set up a For Each loop to loop us through all the members of that group (or, to make it sound like we know what we\u2019re talking about, we loop through all the values stored in the group\u2019s <b>Members<\/b> property):<\/p>\n<pre class=\"codeSample\">For Each objMember In objGroup.Members\n<\/pre>\n<p>So what are we going to do inside this loop? Well, for each member of the local Administrators group we\u2019re going to first check the value of the member\u2019s <b>Class<\/b> attribute; that\u2019s going to tell us whether the member is a user or a group:<\/p>\n<pre class=\"codeSample\">If objMember.Class = \"Group\" Then\n<\/pre>\n<p>If the member <i>is<\/i> a user, well, who cares, right? Therefore, we simply go back to the top of the loop and repeat the process with the next group member. If the member happens to be a group, however, we need to check to make sure that <i>\/atl-fs-001\/<\/i> does <i>not<\/i> appear anywhere in the ADsPath:<\/p>\n<pre class=\"codeSample\">If Not InStr(objMember.AdsPath, strTestString) Then\n<\/pre>\n<p>If <i>\/atl-fs-001\/<\/i> is found then we assume this is a local group; in that case, we go back to the top of the loop and try again with the next group member. If the target text is <i>not<\/i> found then we assume that this is a domain group; in <i>that<\/i> case, we use the following line of code \u2013 and the ADsPath \u2013 to connect to the group account in Active Directory:<\/p>\n<pre class=\"codeSample\">Set objDomainGroup = GetObject(objMember.AdsPath)\n<\/pre>\n<p>What do we do after we make the connection to the group account? Well, for starters, we echo back the group <b>Name<\/b>:<\/p>\n<pre class=\"codeSample\">Wscript.Echo objDomainGroup.Name\n<\/pre>\n<p>We then set up another For Each loop, this one designed to walk through the <b>Members<\/b> of the domain group:<\/p>\n<pre class=\"codeSample\">For Each objDomainMember in objDomainGroup.Members\n<\/pre>\n<p>Inside this loop, we echo back both the <b>FullName<\/b> and the <b>Name<\/b> (i.e., logon name) of each group member, enclosing the Name in parentheses:<\/p>\n<pre class=\"codeSample\">Wscript.Echo objDomainMember.FullName &amp; \" (\" &amp; objDomainMember.Name &amp; \")\"\n<\/pre>\n<p>And then it\u2019s back to the top of the loop where we start over again with the next member of the local Administrators group.<\/p>\n<p>So what\u2019s the end result of all this? Well, suppose our local Administrators group has three members (a local user, a domain user, and a domain group):<\/p>\n<pre class=\"codeSample\">WinNT:\/\/FABRIKAM\/atl-fs-001\/Administrator\nWinNT:\/\/FABRIKAM\/kenmyer\nWinNT:\/\/FABRIKAM\/Finance Managers\n<\/pre>\n<p>When we run through the list of group members we\u2019ll skip the Administrator account; that\u2019s a local user account. We\u2019ll also skip the kenmyer account; that\u2019s a domain user account. When we hit the Finance Managers account we\u2019ll discover that: 1) this is a group; and, 2) this is a domain account. Because of that, we\u2019ll connect to the account in Active Directory and echo back information similar to this:<\/p>\n<pre class=\"codeSample\">Finance Managers\nJonathan Haas (jhaas)\nPilar Ackerman (packerman)\nSyed Abbas (sabbas)\n<\/pre>\n<p>That\u2019s all there is to it, EG. Let us know if you have any questions.<\/p>\n<p>Oh, and in case you\u2019re wondering, we did a quick check and none of the Scripting Guys have ever spent two years in a bathroom. However, we did learn that the Scripting Editor once spent two years in her office. Is that because she\u2019s so dedicated to her job that she couldn\u2019t bear to leave, even for a second? Possibly. However, it\u2019s mostly because we locked the door from the outside and wouldn\u2019t actually <i>let<\/i> her get out.<\/p>\n<p>What can we say? After all, she <i>does<\/i> have a tendency to spoil all the fun around here. (Insisting that we do things right, insisting that we do everything we promised to do, etc. etc. What\u2019s the fun in any of <i>that<\/i>?)<\/p>\n<p><i>Ed<\/i><i>itor\u2019s Note:<\/i> Had they been thinking clearly, which rarely \u2013 if ever \u2013 happens, they would have locked her <i>out<\/i> of her office, not in. But, being as dedicated to her job as she is, the Scripting Editor didn\u2019t bother to correct them on that one.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I manage over 300 servers in our environment. For each server I need to determine the members of the local Administrators account. It\u2019s easy to get a list of local users and domain users that belong to the Admin account; it\u2019s also easy to get a list of any domain groups that [&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,8,5],"class_list":["post-55963","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-active-directory","tag-groups","tag-scripting-guy","tag-searching-active-directory","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I manage over 300 servers in our environment. For each server I need to determine the members of the local Administrators account. It\u2019s easy to get a list of local users and domain users that belong to the Admin account; it\u2019s also easy to get a list of any domain groups that [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/55963","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=55963"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/55963\/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=55963"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=55963"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=55963"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}