{"id":63443,"date":"2007-12-07T01:06:00","date_gmt":"2007-12-07T01:06:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2007\/12\/07\/hey-scripting-guy-how-can-i-map-drives-based-on-membership-in-an-active-directory-group\/"},"modified":"2007-12-07T01:06:00","modified_gmt":"2007-12-07T01:06:00","slug":"hey-scripting-guy-how-can-i-map-drives-based-on-membership-in-an-active-directory-group","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-map-drives-based-on-membership-in-an-active-directory-group\/","title":{"rendered":"Hey, Scripting Guy! How Can I Map Drives Based on Membership in an Active Directory Group?"},"content":{"rendered":"<p><H2><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\"> <\/H2>\n<P>Hey, Scripting Guy! I need to map a drive based on a user\u2019s membership in a particular Active Directory group. However, I have a twist as well: I need to map a different drive depending on whether or not the user is a manager. In other words, I need to map a drive based on both group membership and job title. How do I do that?<BR><BR>&#8212; SA<\/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, SA. You know, it\u2019s been awhile since the Scripting Guy who writes this column has complained about a TV commercial. Why is that? One simple reason: the Scripting Guy who writes this column has come to his senses and no longer wastes his time watching endless hour after endless hour of TV.<\/P>\n<P>No, that\u2019s all right; we didn\u2019t expect you to believe that anyway. The truth is, the Scripting Guy who writes this column watches as much TV as he ever has, maybe even more now that the exercise bikes at his gym all have their own TVs. (True story: Now that each exercise bike has its own TV, the Scripting Guy who writes this column has witnessed a number of people who, rather than ride the bike, simply sit on the thing and watch TV.) But have no fear: today we\u2019re back with another in our <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/apr07\/hey0406.mspx\"><B>continuing series<\/B><\/A> of complaints against TV commercials. Our target this time: a new credit card commercial starring singer\/actress Beyonc\u00e9.<\/P>\n<TABLE id=\"EDD\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Note to Beyonc\u00e9<\/B>. If you\u2019re reading this \u2013 and we have little doubt that you read <I>Hey, Scripting Guy!<\/I> religiously \u2013 please note that we\u2019re not upset with you. It\u2019s just that we don\u2019t fully understand your latest commercial.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Speaking of which, in this commercial, Beyonc\u00e9 is preparing to leave on tour. First stop? Madrid, Spain. Right before she leaves, Beyonc\u00e9 promises to pick up presents for her niece and nephew. Her niece wants a kimono, and her nephew wants a boomerang.<\/P>\n<TABLE id=\"ESD\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P><B>Note to Beyonc\u00e9<\/B>. Admittedly, we aren\u2019t privy to your entire schedule. Still, if you\u2019re bound for Madrid, Spain wouldn\u2019t it have been better to promise to bring back something (anything!) other than a kimono or a boomerang? Having recently returned from Spain (albeit <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/teched07\/eu.mspx\"><B>Barcelona<\/B><\/A>, not Madrid), the Scripting Guy who writes this column doesn\u2019t recall seeing very many boomerangs or kimonos for sale.<\/P>\n<P>But, then again, there\u2019s always the possibility that Beyonc\u00e9 and the Scripting Guy who writes this column don\u2019t shop at the same stores.<\/P>\n<P>Hey, we didn\u2019t say that they <I>do<\/I> shop at different stores. Just that it\u2019s <I>possible<\/I> that they shop at different stores.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Anyway, between travel, rehearsals, photo shoots, and, well, whatever else it is that Beyonc\u00e9 does, every minute of her day is booked solid. So, obviously, she forgets about her promise to her niece and nephew, doesn\u2019t she? Heaven forbid! Not only that, but she refuses to pawn her shopping off on someone else; in fact, when an assistant asks if she should go pick up the gifts Beyonc\u00e9 says, \u201cNo, I\u2019d rather do that myself.\u201d<\/P>\n<P>And she does: she logs on to the Internet and buys her nephew a boomerang.<\/P>\n<P>Now, the Scripting Guys think it\u2019s great that a big star like Beyonc\u00e9 still does her own shopping; unlike her, we\u2019ve had our personal assistants do our shopping for us for years now. But is going online and buying a boomerang really doing your own shopping? And does buying a boomerang online truly count as bringing someone back a <I>souvenir<\/I>? The Scripting Guy who writes this column is a bit skeptical, to say the least.<\/P>\n<P>Although he does like the message that this commercial sends: thanks to credit cards and the Internet, you can do all sorts of wonderful things for your family, and without having to do anything distasteful or inconvenient. <\/P>\n<P>Like, you know, actually doing something for your family.<\/P>\n<P>But rest assured, SA: some things in life are still done the old-fashioned way. The Scripting Guys might have their personal assistants do their shopping for them, but when it comes time to write scripts that can map drives based on membership in an Active Directory group, well, the Scripting Guys still write these themselves, using the same tools and the same techniques that their great-great grandfathers used, back in the old country. The result? This:<\/P><PRE class=\"codeSample\">On Error Resume Next<\/p>\n<p>Set objADSysInfo = CreateObject(&#8220;ADSystemInfo&#8221;)\nstrUser = objADSysInfo.UserName<\/p>\n<p>Set objUser = GetObject(&#8220;LDAP:\/\/&#8221; &amp; strUser)<\/p>\n<p>For Each strGroup in objUser.memberOf\n    Set objGroup = GetObject(&#8220;LDAP:\/\/&#8221; &amp; strGroup)\n    If objGroup.CN = &#8220;Finance Department&#8221; Then\n        strTitle = objUser.Title\n        If strTitle = &#8220;Manager&#8221; Then\n            Set objNetwork = CreateObject(&#8220;Wscript.Network&#8221;)\n            objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-001\\public\\managers&#8221;\n        Else\n            Set objNetwork = CreateObject(&#8220;Wscript.Network&#8221;)\n            objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-001\\public\\users&#8221;\n        End If\n        Exit For\n    End If     \nNext\n<\/PRE>\n<P>Good point; this <I>would<\/I> have been a much better gift for her nephew than a boomerang, wouldn\u2019t it? Wonder if we can talk them into redoing that commercial?<\/P>\n<P>Until then, let\u2019s see if we can figure out how the script actually works. To begin with, we\u2019re assuming that this script is going to run as a logon script. In fact, it pretty much <I>has<\/I> to run as a logon script; that\u2019s because there\u2019s no simple and straightforward method for mapping drives on remote computers.<\/P>\n<TABLE id=\"EBF\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Note<\/B>. So does that mean there\u2019s a more complicated and not-so-straightforward method for mapping drives on remote computers? Sure; hey, if you\u2019re willing to settle for complicated and not-so-straightforward you can do almost anything. For a hint or two on how you might map a drive on a remote computer, see <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/sept04\/hey0901.mspx\"><B>this Hey, Scripting Guy! column<\/B><\/A>.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Because this <I>is<\/I> a logon script, we start out by creating an instance of the <B>ADSystemInfo<\/B> object, an object that returns information about the logged-on user, the local computer, and the local domain. What <I>kind<\/I> of information does ADSystemInfo return? Well, for one thing, it can tell us the DN (distinguished name) of the logged-on user. In fact, in this line of code we grab the DN for the logged-on user and store it in a variable named strUser:<\/P><PRE class=\"codeSample\">strUser = objADSysInfo.UserName\n<\/PRE>\n<P>As you probably know, the DN provides us with the \u201caddress\u201d to the user\u2019s actual Active Directory user account; that\u2019s because the DN looks something like this:<\/P><PRE class=\"codeSample\">CN=Ken Myer,OU=Europe,DC=fabrikam,DC=com\n<\/PRE>\n<P>If we want to bind to that user account (and we do; that\u2019s the only way to determine which groups the user belongs to) all we have to do is take the value of strUser, tack <B>LDAP:\/\/<\/B> to the front of it, and then pass <I>that<\/I> value (which just happens to be the user\u2019s ADsPath) to the <B>Get-Object<\/B> method. In other words, we just have to execute the following line of code:<\/P><PRE class=\"codeSample\">Set objUser = GetObject(&#8220;LDAP:\/\/&#8221; &amp; strUser)\n<\/PRE>\n<P>As you might also know, each Active Directory user account includes an attribute named <B>memberOf<\/B>; as the name implies, this attribute contains a list of all the groups that the user belongs to. That means that our next task is to cycle through that list of groups and determine whether the user is a member of a particular group (and, if he or she is, then determine whether or not the user is a manager). How are we going to do that? Well, for starters, we\u2019re going to set up a For Each loop that walks us through each of the groups included in the memberOf attribute:<\/P><PRE class=\"codeSample\">For Each strGroup in objUser.memberOf\n<\/PRE>\n<P>Each group that the user belongs to is stored in the memberOf attribute by the group\u2019s DN. (And yes, groups also have DNs; for that matter, pretty much <I>everything<\/I> in Active Directory has a DN.) Because DN\u2019s are no fun to work with, our next step is to use this line of code to bind directly to the group account in Active Directory:<\/P><PRE class=\"codeSample\">Set objGroup = GetObject(&#8220;LDAP:\/\/&#8221; &amp; strGroup)\n<\/PRE>\n<P>Why do we bind to the group account? Well, as you know, what we\u2019re doing here is looping through all the groups that the user belongs to, doing our best to determine if the user is a member of a specified group (in this case, the Finance Department group). If we wanted to, we could do this by determining if any of the user\u2019s groups are equal to a specified DN:<\/P><PRE class=\"codeSample\">If strGroup = &#8220;CN=Finance Department,OU=Finance,OU=North America,DC=fabrikam,dc=com&#8221; Then\n<\/PRE>\n<P>That works, but it\u2019s a bit cumbersome, to say the least. Therefore, to make things a bit easier on ourselves, we bind to the group account and retrieve the value of the <B>CN<\/B> attribute. In turn, that allows us to write an If-Then statement that looks like this:<\/P><PRE class=\"codeSample\">If objGroup.CN = &#8220;Finance Department&#8221; Then\n<\/PRE>\n<P>That\u2019s a little easier for human beings (or even Scripting Guys, for that matter) to deal with.<\/P>\n<TABLE id=\"EBH\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Note<\/B>. Another benefit to binding to the group account? When you sit down to write the script, there\u2019s a good chance that you\u2019ll already know the CN of the group (Finance Department). There\u2019s probably far less chance that you\u2019ve memorized the DNs for all your Active Directory groups. (And, if you <I>have<\/I> memorized the DNs for all your Active Directory groups, well, does the phrase \u201cget a life\u201d mean anything to you?)<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>So what if the first group in the collection <I>doesn\u2019t<\/I> have a CN equal to <I>Finance Department<\/I>? That\u2019s fine; in that case we simply return to the top of the loop and try again with the next group. If it turns out that none of the groups has a CN equal to <I>Finance Department<\/I>, well, that\u2019s also fine: that just means that user isn\u2019t a member of the Finance Department group. In that case the script simply terminates, and no drives get mapped.<\/P>\n<P>Ah, but suppose one of the groups <I>does<\/I> have a CN equal to <I>Finance Department<\/I>. In that case we execute the following two lines of code:<\/P><PRE class=\"codeSample\">strTitle = objUser.Title\nIf strTitle = &#8220;Manager&#8221; Then\n<\/PRE>\n<P>In line 1, we\u2019re simply grabbing the value of the user\u2019s <B>Title<\/B> attribute and then storing it in a variable named strTitle; in line 2, we\u2019re then checking to see if that title happens to be equal to <I>Manager<\/I>.<\/P>\n<P>And what if the user <I>is<\/I> a manager? Well, in that case he or she will get drive X mapped to \\\\atl-fs-001\\pubic\\managers:<\/P><PRE class=\"codeSample\">Set objNetwork = CreateObject(&#8220;Wscript.Network&#8221;)\nobjNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-001\\public\\managers&#8221;\n<\/PRE>\n<P>And if the user is a member of the Finance Department group but <I>isn\u2019t<\/I> a manager? Then he or she gets a drive mapped to \\\\atl-fs-001\\public\\users instead:<\/P><PRE class=\"codeSample\">Set objNetwork = CreateObject(&#8220;Wscript.Network&#8221;)\nobjNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-001\\public\\users&#8221;\n<\/PRE>\n<P>Either way, drive X gets mapped. And then we call the <B>Exit For<\/B> statement to exit the loop and bring the script to an end.<\/P>\n<P>It probably goes without saying that this particular script only checks for membership in a single group (Finance Department) and then checks to see if the user is (or isn\u2019t) a manager. However, you could easily modify the script to check for membership in other groups, or to check for other job titles. Just copy, paste, and tweak various portions of the script as needed. For example, this modified code checks to see if the user is a member of the Finance Department group <I>or<\/I> a member of the Human Resources Department group:<\/P><PRE class=\"codeSample\">If objGroup.CN = &#8220;Finance Department&#8221; Then\n    strTitle = objUser.Title\n    If strTitle = &#8220;Manager&#8221; Then\n        Set objNetwork = CreateObject(&#8220;Wscript.Network&#8221;)\n        objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-001\\public\\managers&#8221;\n    Else\n        Set objNetwork = CreateObject(&#8220;Wscript.Network&#8221;)\n        objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-001\\public\\users&#8221;\n    End If\n    Exit For<\/p>\n<p>ElseIf objGroup.CN = &#8220;Human Resources Department&#8221; Then<\/p>\n<p>    strTitle = objUser.Title\n    If strTitle = &#8220;Manager&#8221; Then\n        Set objNetwork = CreateObject(&#8220;Wscript.Network&#8221;)\n        objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-001\\public\\hrmanagers&#8221;\n    Else\n        Set objNetwork = CreateObject(&#8220;Wscript.Network&#8221;)\n        objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-001\\public\\hrusers&#8221;\n    End If\n    Exit For<\/p>\n<p>End If\n<\/PRE>\n<P>You know, that\u2019s a good question: what happens if a user is a member of <I>both<\/I> groups? Well, in that case, the user will get a drive mapping based on whichever group gets encountered first. (That is, whichever group shows up first in the For Each loop.) If that\u2019s a problem (that is, if you\u2019re a member of group A and a member of group B and you want group A to always take precedence), you could modify the script to keep track of all the targeted groups that the user belongs to, then write some code to pick the \u201cbest\u201d group out of that collection. But that\u2019s something we\u2019ll have to tackle on another day.<\/P>\n<P>Tomorrow? We\u2019ll see. <\/P>\n<P>Before we go, however, we\u2019d like to point out that, according to published reports, Beyonc\u00e9 makes approximately $18-20 million every year. Which is good news: that means that the system works. For one thing, the Scripting Guys have the moral high ground: we truly do write our own scripts, and we don\u2019t make silly TV commercials. For another, we also make way more money each year than Beyonc\u00e9 does.<\/P>\n<P>Well, before taxes, anyway.<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I need to map a drive based on a user\u2019s membership in a particular Active Directory group. However, I have a twist as well: I need to map a different drive depending on whether or not the user is a manager. In other words, I need to map a drive based on [&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,185,12,20,5],"class_list":["post-63443","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-active-directory","tag-groups","tag-scripting-guy","tag-shared-folders-and-mapped-drives","tag-storage","tag-user-accounts","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I need to map a drive based on a user\u2019s membership in a particular Active Directory group. However, I have a twist as well: I need to map a different drive depending on whether or not the user is a manager. In other words, I need to map a drive based on [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/63443","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=63443"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/63443\/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=63443"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=63443"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=63443"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}