{"id":63813,"date":"2007-10-12T04:03:00","date_gmt":"2007-10-12T04:03:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2007\/10\/12\/hey-scripting-guy-how-can-i-map-drives-based-on-ip-address\/"},"modified":"2007-10-12T04:03:00","modified_gmt":"2007-10-12T04:03:00","slug":"hey-scripting-guy-how-can-i-map-drives-based-on-ip-address","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-map-drives-based-on-ip-address\/","title":{"rendered":"Hey, Scripting Guy! How Can I Map Drives Based on IP Address?"},"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 have been using <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/dec04\/hey1210.mspx\"><B>your script<\/B><\/A> that maps drives based on group membership, and it works just fine. However, I need to modify the script so that drive mappings are also based on the location of the computer (more specifically, on the computer IP address). For example, we have a remote site that uses an ISDN connection and I don\u2019t want the drive mappings to happen across this link; instead I would like the drive mappings to go to a local server. How can I modify your script so that it uses both group membership and IP address when mapping drives?<BR><BR>&#8212; BT<\/P>\n<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> <\/P>\n<P>Hey, BT. Before we begin, we\u2019d like to give a special Scripting Guys shout-out to our new friends at Microsoft, friends who have begun reading this column and are, quite literally, hanging on our every word. Welcome aboard, guys! We just hope that you won\u2019t be too disappointed in today\u2019s column; after all, today the Scripting Guys are all business, with none of our usual fluff and nonsense.<\/P>\n<P>Oh, what the heck; we have time for one little joke, don\u2019t we? A blonde, a brunette, and a redhead walk into a bar. \u201cHey, bartender,\u201d says the blonde. \u201cWe\u2019re three beautiful young girls forced to spend the night alone in a strange town. Can you recommend a good Internet search engine?\u201d<\/P>\n<P>\u201dWhy, <A href=\"http:\/\/www.live.com\/\" target=\"_blank\"><B>Windows Live Search<\/B><\/A>, of course,\u201d replied the bartender. \u201cIt\u2019s not only a good Internet search engine, it\u2019s the <I>only<\/I> Internet search engine.\u201d<\/P>\n<P>OK, so maybe it\u2019s not a particularly <I>funny<\/I> joke. But, then again, Microsoft people have their own, unique sense of humor.<\/P>\n<P>As we Scripting Guys are reminded over and over again.<\/P>\n<P>Besides, it\u2019s time to get down to business. (Although, if we haven\u2019t already done so, we should mention that <A href=\"http:\/\/www.live.com\/\" target=\"_blank\"><B>Windows Live Search<\/B><\/A> is not only a good Internet search engine, it\u2019s the <I>only<\/I> Internet search engine. Or at least the only one you should care about.) <\/P>\n<P>As BT noted, he\u2019s been using a logon script (discussed in a <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/dec04\/hey1210.mspx\"><B>previous column<\/B><\/A>) as a way to map network drives based on a user\u2019s membership in a particular Active Directory group. However, he now needs to add in an additional stipulation based on the computer\u2019s IP address (or, to be a bit more precise, the third octet in the IP address). For example, if the user belongs to the Finance Users group and the computer\u2019s IP address is 192.168.<B>36<\/B>.1 then a drive is mapped to \\\\atl-fs-<B>01<\/B>\\finance. Otherwise, the drive is mapped to \\\\atl-fs-<B>02<\/B>\\finance.<\/P>\n<P>This, by the way, seems to be a fairly common question: we\u2019ve gotten several emails over the past few weeks asking how drives can be mapped based on IP address. Today\u2019s script should help answer those questions.<\/P>\n<P>\n<TABLE id=\"EQE\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P><B>Note<\/B>. We\u2019ve also gotten several emails over the past few weeks asking if we could recommend a good Internet search engine. You bet we can: <A href=\"http:\/\/www.live.com\/\" target=\"_blank\"><B>Windows Live Search<\/B><\/A>.<\/P>\n<P>Windows Live Search. It\u2019s not only a good Internet search engine, it\u2019s the <I>only<\/I> Internet search engine.<\/P>\n<P><B>Ed<\/B><B>itor\u2019s Note<\/B>: In the interest of full disclosure and total honesty, we will admit that Windows Live Search might not be the only Internet search engine. (We said <I>might<\/I>.) If it isn\u2019t, well, just pretend it is.<\/P><\/TD><\/TR><\/TBODY><\/TABLE><\/P>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>So how can we help BT? Like this:<\/P><PRE class=\"codeSample\">On Error Resume Next<\/p>\n<p>Set objSysInfo = CreateObject(&#8220;ADSystemInfo&#8221;)\nSet objNetwork = CreateObject(&#8220;Wscript.Network&#8221;)<\/p>\n<p>strUserPath = &#8220;LDAP:\/\/&#8221; &amp; objSysInfo.UserName\nSet objUser = GetObject(strUserPath)<\/p>\n<p>strComputer = &#8220;.&#8221;<\/p>\n<p>Set objWMIService = GetObject(&#8220;winmgmts:\\\\&#8221; &amp; strComputer &amp; &#8220;\\root\\cimv2&#8221;)<\/p>\n<p>Set colItems = objWMIService.ExecQuery _\n    (&#8220;Select * From Win32_NetworkAdapterConfiguration Where IPEnabled = True&#8221;)<\/p>\n<p>For Each objItem in colItems\n    For Each objAddress in objItem.IPAddress\n        arrIPAddress = Split(objAddress, &#8220;.&#8221;)\n        If arrIPAddress(0) &lt;&gt; 0 AND arrIPAddress(0) &lt;&gt; 169 Then\n            strAddress = arrIPAddress(2)\n            Exit For\n        End If\n    Next\n    Exit For\nNext<\/p>\n<p>For Each strGroup in objUser.MemberOf\n    strGroupPath = &#8220;LDAP:\/\/&#8221; &amp; strGroup\n    Set objGroup = GetObject(strGroupPath)\n    strGroupName = objGroup.CN<\/p>\n<p>    Select Case strGroupName\n        Case &#8220;Finance Users&#8221;\n            If strAddress = 36 Then\n                objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-01\\finance&#8221;\n                Exit For\n            Else\n                objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-02\\finance&#8221;\n                Exit For\n            End If\n        Case &#8220;Human Resource Users&#8221; \n            If strAddress = 36 Then\n                objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-01\\hr&#8221;\n                Exit For\n            Else\n                objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-02\\hr&#8221;\n                Exit For\n            End If\n        Case &#8220;Manufacturing Users&#8221;\n            If strAddress = 36 Then\n                objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-01\\manufacturing&#8221;\n                Exit For\n            Else\n                objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-02\\manufacturing&#8221;\n                Exit For\n            End If\n        Case &#8220;Shipping and Receiving Users&#8221;\n            If strAddress = 36 Then\n                objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-01\\shipping&#8221;\n                Exit For\n            Else\n                objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-02\\shipping&#8221;\n                Exit For\n            End If\n    End Select\nNext\n<\/PRE>\n<P>By the way, don\u2019t be deterred by the length of this script; it\u2019s this long simply because we\u2019ve included drive mapping code for 4 or 5 groups. As you\u2019re about to see, much of this script is boilerplate: it can be copied and pasted, then turned into production-ready code simply by making an occasional tweak or two. (Like changing the group name and the network path.)<\/P>\n<P>We start things out by creating instances of the <B>ADSystemInfo<\/B> and <B>Wscript.Network<\/B> objects; we\u2019ll use ADSystemInfo to help us bind to the Active Directory user account for the local user, and we\u2019ll use the Wscript.Network object to map the network drive. After creating the two objects we then construct the ADsPath for the logged-on user by using this line of code:<\/P><PRE class=\"codeSample\">strUserPath = &#8220;LDAP:\/\/&#8221; &amp; objSysInfo.UserName\n<\/PRE>\n<P>And once we have the ADsPath we can then bind to the user account in Active Directory by executing <I>this<\/I> line of code:<\/P><PRE class=\"codeSample\">Set objUser = GetObject(strUserPath)\n<\/PRE>\n<P>\n<TABLE id=\"EBG\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P><B>Note<\/B>. OK, admittedly, that\u2019s a pretty cursory explanation of ADSystemInfo and what we can use it for. For more information, take a look at our <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/dec04\/hey1210.mspx\"><B>previous column<\/B><\/A> on mapping drives based on group membership.<\/P>\n<P>Or, even better, use <A href=\"http:\/\/www.live.com\/\" target=\"_blank\"><B>Windows Live Search<\/B><\/A> and search the Internet for more information.<\/P>\n<P>Windows Live Search. It\u2019s not only a good \u2013 oh, right; we did say that already, didn\u2019t we?<\/P><\/TD><\/TR><\/TBODY><\/TABLE><\/P>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Our next step is to determine the IP address for the local computer, something which is a tad bit trickier than it might sound. (Why? Because computers can have multiple network adapters and\/or multiple IP addresses.) To begin with, we use this block of code to connect to the WMI service on the local computer:<\/P><PRE class=\"codeSample\">strComputer = &#8220;.&#8221;<\/p>\n<p>Set objWMIService = GetObject(&#8220;winmgmts:\\\\&#8221; &amp; strComputer &amp; &#8220;\\root\\cimv2&#8221;)\n<\/PRE>\n<P>And then we use <I>this<\/I> line of code to retrieve a collection of all the \u201creal\u201d network adapters installed on that computer:<\/P><PRE class=\"codeSample\">Set colItems = objWMIService.ExecQuery _\n    (&#8220;Select * From Win32_NetworkAdapterConfiguration Where IPEnabled = True&#8221;)\n<\/PRE>\n<P>\n<TABLE id=\"EDH\" 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>. What do we mean by \u201creal\u201d network adapters? Well, for better or worse (probably worse, to tell you the truth), the <B>Win32_NetworkAdapterConfiguration<\/B> class returns information about a whole host of virtual network adapters in additional to your real, live network adapters. Fortunately, we can weed out most of those phantom adapters by including a Where clause that limits returned data to those adapters where the <B>IPEnabled<\/B> property is True. Which is just exactly what we did.<\/P><\/TD><\/TR><\/TBODY><\/TABLE><\/P>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>That brings us to the following block of code:<\/P><PRE class=\"codeSample\">For Each objItem in colItems\n    For Each objAddress in objItem.IPAddress\n        arrIPAddress = Split(objAddress, &#8220;.&#8221;)\n        If arrIPAddress(0) &lt;&gt; 0 AND arrIPAddress(0) &lt;&gt; 169 Then\n            strAddress = arrIPAddress(2)\n            Exit For\n        End If\n    Next\n    Exit For\nNext\n<\/PRE>\n<P>What we\u2019re doing here is setting up a For Each loop to loop through our collection of network adapters. We then immediately set up a second For Each loop, this one designed to loop through all the possible IP addresses for each adapter. (Because a single adapter can have more than one IP address, the <B>IPAddress<\/B> property <B>stores information as an array<\/B>.) Inside this second loop we use the <B>Split<\/B> function to split the first IP address on the period. If we have the IP address 192.168.1.2 that means we\u2019ll end up with an array named arrIPAddress that contains the following items:<\/P>\n<P>\n<TABLE border=\"0\" cellSpacing=\"0\" cellPadding=\"0\">\n<TBODY>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>192<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>168<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>1<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>2<\/P><\/TD><\/TR><\/TBODY><\/TABLE><\/P>\n<P>See how that works? Good. That means we\u2019re ready to go on.<\/P>\n<P>In order to ensure that we have a valid IP address, we next execute this line of code:<\/P><PRE class=\"codeSample\">If arrIPAddress(0) &lt;&gt; 0 AND arrIPAddress(0) &lt;&gt; 169 Then\n<\/PRE>\n<P>This simply makes sure that the first octet in the IP address (that is, item 0 in our array) is neither 0 nor 169. If the first octet is 0, then you\u2019re probably looking at an adapter that has not had an IP address assigned to it; if the first octet is 169 then you\u2019re looking at an adapter that is using an auto-assigned IP address. If neither of these conditions is True we\u2019re going to assume that we have a valid IP address. With that in mind, we use the following line of code to assign item 2 in the array (the third octet in the IP address) to a variable named strAddress:<\/P><PRE class=\"codeSample\">strAddress = arrIPAddress(2)\n<\/PRE>\n<P>\n<TABLE id=\"ERAAC\" 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>. Remember, the first item in an array has the index number 0 and the second item in an array has the index number 1. That\u2019s why we reference arrIPAddress(2) when retrieving the value of the third octet; the third item in an array has the index number 2.<\/P><\/TD><\/TR><\/TBODY><\/TABLE><\/P>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Once we have a valid address we then call the <B>Exit For<\/B> statement to exit our For Each loop. That means that we\u2019re going to use the first valid IP address we find, even if a computer has multiple IP addresses assigned to it. (Which probably won\u2019t cause too many problems; logon scripts are typically run against client machines, and client machines typically <I>don\u2019t<\/I> have multiple IP addresses assigned to them.)<\/P>\n<P>Now we\u2019re ready to start looping through the collection of groups that the logged-on user belongs to, something we do using this line of code (the <B>MemberOf<\/B> attribute is a multi-valued attribute containing a list of all the groups the user is a member of):<\/P><PRE class=\"codeSample\">For Each strGroup in objUser.MemberOf\n<\/PRE>\n<P>What do we do inside this loop? Well, to begin with, for each group in the collection we use this block of code to bind to the group account in Active Directory and retrieve the value of the group\u2019s <B>CN<\/B> (common name) attribute:<\/P><PRE class=\"codeSample\">strGroupPath = &#8220;LDAP:\/\/&#8221; &amp; strGroup\nSet objGroup = GetObject(strGroupPath)\nstrGroupName = objGroup.CN\n<\/PRE>\n<P>From there we set up a <B>Select Case<\/B> statement and start checking to see if the user is a member of a particular group. If he or she is, we then map drive X accordingly. For example:<\/P><PRE class=\"codeSample\">Case &#8220;Finance Users&#8221;\n    If strAddress = 36 Then\n        objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-01\\finance&#8221;\n        Exit For\n    Else\n        objNetwork.MapNetworkDrive &#8220;X:&#8221;, &#8220;\\\\atl-fs-02\\finance&#8221;\n        Exit For\n    End If\n<\/PRE>\n<P>It shouldn\u2019t be too hard to see what we\u2019re doing here. We retrieve the name of the first group that the user belongs to and check to see if that group happens to be named Finance Users. If the group <I>is<\/I> named Finance Users, we then check to see if the third octet of our IP address is equal to 36; that\u2019s what this line of code is for:<\/P><PRE class=\"codeSample\">If strAddress = 36 Then\n<\/PRE>\n<P>If the third octet is equal to 36 we then map drive X to \\\\atl-fs-01\\finance; if the third octet is <I>not<\/I> equal to 36 then we map the drive to \\\\atl-fs-02\\finance. In either case, once we\u2019ve mapped drive X we then use the Exit For statement to exit our For Each loop; this will help prevent an error from occurring if a user happens to belong to more than one of the target groups. (Why would an error occur? Because we might try mapping drive X to \\\\atl-fs-01\\shipping even though we\u2019ve already mapped drive X to \\\\atl-fs-01\\finance. That\u2019s a no-no.)<\/P>\n<P>\n<TABLE id=\"EBCAC\" 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 suppose a user <I>does<\/I> belong to multiple groups; would it possible to map multiple drives, assigning an unused drive letter as needed? Yes, although, needless to say, that would require some additional work. We don\u2019t have time to discuss that additional work today, but we can at least point you to <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/jan05\/hey0122.mspx\"><B>another column<\/B><\/A> that shows you how to determine the next available drive letter on a computer.<\/P><\/TD><\/TR><\/TBODY><\/TABLE><\/P>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>We hope that answers your question, BT. As for the Scripting Guys, it\u2019s time to go search the Internet using <A href=\"http:\/\/www.live.com\/\" target=\"_blank\"><B>Windows Live Search<\/B><\/A>. Windows Live Search. It\u2019s not only a good search engine, it\u2019s \u2013 well, you can fill in the rest yourself. We\u2019ve got searching to do!<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I have been using your script that maps drives based on group membership, and it works just fine. However, I need to modify the script so that drive mappings are also based on the location of the computer (more specifically, on the computer IP address). For example, we have a remote site [&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":[3,185,12,5],"class_list":["post-63813","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-scripting-guy","tag-shared-folders-and-mapped-drives","tag-storage","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I have been using your script that maps drives based on group membership, and it works just fine. However, I need to modify the script so that drive mappings are also based on the location of the computer (more specifically, on the computer IP address). For example, we have a remote site [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/63813","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=63813"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/63813\/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=63813"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=63813"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=63813"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}