{"id":63973,"date":"2007-09-21T02:14:00","date_gmt":"2007-09-21T02:14:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2007\/09\/21\/how-can-i-dynamically-show-available-drive-letters-in-a-list-box\/"},"modified":"2007-09-21T02:14:00","modified_gmt":"2007-09-21T02:14:00","slug":"how-can-i-dynamically-show-available-drive-letters-in-a-list-box","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-dynamically-show-available-drive-letters-in-a-list-box\/","title":{"rendered":"How Can I Dynamically Show Available Drive Letters in a List Box?"},"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! I\u2019m using an HTA as a drive-mapping application. I\u2019d like to be clever about this and have the available drive letters appear in a list box. How can I dynamically show all the drive letters available on a computer?<BR><BR>&#8212; JT<\/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, JT. You know, just <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/sept07\/hey0918.mspx\"><B>the other day<\/B><\/A> the Scripting Guy who writes this column was lamenting a truly lost weekend for Seattle-area sports fans. Well, we\u2019re happy to report that things are finally looking up. After all, last night the Mariners\u2019 Jeff Weaver \u2013 our top free agent acquisition, a \u201cfree\u201d agent making more than $8 million this year \u2013 won his seventh game of the season, defeating the Oakland A\u2019s 8-7.<\/P>\n<P>And no, that\u2019s not a misprint: 7 wins, and 8 million dollars. Admittedly, that <I>sounds<\/I> like a lot of money; more than $1 million for each victory. But look at it this way: if Jeff Weaver hadn\u2019t won those 7 games, the Mariners wouldn\u2019t make the playoffs. But <I>with<\/I> those seven wins, and with that outlay of $8 million, the Mariners will definitely make the \u2013 uh, never mind. We\u2019re going to have to rethink our calculations.<\/P>\n<TABLE class=\"dataTable\" id=\"EKD\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P><B>Note<\/B>. It\u2019s obviously not the place of the Scripting Guy who writes this column to tell the Seattle Mariners how to run their team. (Although \u2026.) On the other hand, it cost $8 million for the Mariners to have Jeff Weaver and not make the playoffs. Suppose next year they cut Jeff Weaver and pay the Scripting Guy who writes this column a measly $1 million to take his place. Will the Mariners make the playoffs with the Scripting Guy as part of their pitching rotation? Probably not. But they <I>would<\/I> save $7 million.<\/P>\n<P>And yes, making $1 million a year <I>would<\/I> be a drastic pay cut for the Scripting Guy who writes this column. But he\u2019s willing to do that for the chance to play major league baseball.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Hard as this might be to believe, however, Jeff Weaver winning his seventh game of the year isn\u2019t the only exciting news to hit the Seattle area. In addition to that milestone, the whole town has been <I>thrilled<\/I> to hear about a script that can dynamically display available drive letters in a list box. Could such a script truly exist? Let\u2019s see for ourselves: <\/P><PRE class=\"codeSample\">&lt;SCRIPT Language=&#8221;VBScript&#8221;&gt;\n    Sub Window_onLoad\n        strComputer = &#8220;.&#8221;<\/p>\n<p>        Set objWMIService = GetObject(&#8220;winmgmts:\\\\&#8221; &amp; strComputer &amp; &#8220;\\root\\cimv2&#8221;)<\/p>\n<p>        Set colDisks = objWMIService.ExecQuery(&#8220;Select * from Win32_LogicalDisk&#8221;)<\/p>\n<p>        Set objDictionary = CreateObject(&#8220;Scripting.Dictionary&#8221;)<\/p>\n<p>        For Each objDisk in colDisks\n            objDictionary.Add objDisk.DeviceID, objDisk.DeviceID\n        Next<\/p>\n<p>        For i = 67 to 90\n            strDrive = Chr(i) &amp; &#8220;:&#8221;\n            If objDictionary.Exists(strDrive) Then\n            Else\n                strDrives = strDrives &amp; strDrive &amp; vbCrLf\n            End If\n        Next<\/p>\n<p>        arrDrives = Split(strDrives, vbCrlf)<\/p>\n<p>        For Each strDrive In arrDrives\n            Set objOption = Document.createElement(&#8220;OPTION&#8221;)\n            objOption.Text = strDrive\n            objOption.Value = strDrive\n            AvailableDrives.Add(objOption)\n        Next\n    End Sub\n&lt;\/SCRIPT&gt;<\/p>\n<p>&lt;body&gt;\n    &lt;select size=&#8221;5&#8243; name=&#8221;AvailableDrives&#8221; style=&#8221;width:100&#8243;&gt;\n    &lt;\/select&gt;\n&lt;\/body&gt;\n<\/PRE>\n<P>Before we launch into the discussion of this script and how it works, we should note that this is <I>not<\/I> a complete solution for mapping a network drive; all it does it demonstrate how to retrieve the available drive letters and add those drive letters to a list box. Are we going to show you a more complete solution before we call it a day? Maybe, but we aren\u2019t going to tell you right now. After all, if we did that, you\u2019d be tempted to skip directly to that portion of the article, which means you\u2019d miss all the other cool things in today\u2019s column.<\/P>\n<TABLE class=\"dataTable\" id=\"EIE\" 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>. Not that there <I>are<\/I> any cool things in today\u2019s column, mind you. But just in case there <I>are<\/I>, well, we\u2019d hate for you to miss them.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>The HTA itself is pretty simple: it consists solely of a list box named AvailableDrives, a list box that displays five items at a time (that\u2019s what the <B>Size<\/B> property is for) and is 100 pixels wide. Here\u2019s the HTML tagging for displaying the list box:<\/P><PRE class=\"codeSample\">&lt;select size=&#8221;5&#8243; name=&#8221;AvailableDrives&#8221; style=&#8221;width:100&#8243;&gt;\n&lt;\/select&gt;\n<\/PRE>\n<P>And you\u2019re right: this list box <I>doesn\u2019t<\/I> have any options, does it? (Sort of like the Scripting Guys when it comes to career choices.) But don\u2019t worry; as you might recall, the whole idea of this HTA is to add these options programmatically. And we\u2019re going to do just that, in due time.<\/P>\n<TABLE class=\"dataTable\" id=\"EEF\" 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>. What if you aren\u2019t totally sure what we mean when we talk about HTAs, list boxes, and &lt;SELECT&gt; statements? That\u2019s all right; just take a peek at our <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/htas.mspx\"><B>HTA Developer\u2019s Center<\/B><\/A> for some more information.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>OK, so much for displaying a list box onscreen. Now let\u2019s talk about the <I>good<\/I> stuff: dynamically adding available drive letters to that list box.<\/P>\n<P>We\u2019d like our HTA to automatically load those drive letters each time our little application is opened or refreshed. How do we do that? That\u2019s easy: we put the list box-updating code in a subroutine named Window_onLoad:<\/P><PRE class=\"codeSample\">&lt;SCRIPT Language=&#8221;VBScript&#8221;&gt;\n    Sub Window_onLoad\n<\/PRE>\n<P>If you\u2019re familiar with HTML programming you know that the Window_onLoad subroutine is automatically executed any time a Web page (or HTA) is loaded or refreshed. What if you\u2019re <I>not<\/I> familiar with HTML programming? That\u2019s fine: now <I>you<\/I> know that the Window_onLoad subroutine is automatically executed any time a Web page (or HTA) is loaded or refreshed.<\/P>\n<P>Inside the subroutine, we kick things off by connecting to the WMI service on the local computer. Could we run this HTA against a <I>remote<\/I> computer? Well, kind of. It\u2019s easy enough to get drive letter information off a remote machine; however, mapping drives on that remote computer is a whole \u2018nother story, and one we won\u2019t get into today. (For a hint as to how you might go about doing that, take a gander at <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/sept04\/hey0901.mspx\"><B>this Hey, Scripting Guy! column<\/B><\/A>.<\/P>\n<P>After we connect to the WMI service, we then use the <B>ExecQuery<\/B> method to return information about all the <I>used<\/I> drives on the computer, both local drives and mapped network drives:<\/P><PRE class=\"codeSample\">Set colDisks = objWMIService.ExecQuery(&#8220;Select * from Win32_LogicalDisk&#8221;)\n<\/PRE>\n<P>What\u2019s that? You\u2019re saying that all we\u2019ve done so far is return a collection of the <I>unavailable<\/I> drive letters (that is, drive letters already in use)? You\u2019re saying that what we need to do is figure out which drive letters are <I>available<\/I>? Hmmm, that <I>is<\/I> a bit of a dilemma, isn\u2019t it? Wonder how the Scripting Guys will work their way out of <I>this<\/I> one?<\/P>\n<P>And no, we\u2019re not going to show you <I>that<\/I>, either, at least not right now. Before we can do any of that we need to create an instance of the <B>Scripting.Dictionary<\/B> object. Once we have an instance of the Dictionary object in hand we then execute this block of code:<\/P><PRE class=\"codeSample\">For Each objDisk in colDisks\n    objDictionary.Add objDisk.DeviceID, objDisk.DeviceID\nNext\n<\/PRE>\n<P>What are we doing there? What we\u2019re doing there is looping through the collection of disk drives and, for each drive in the collection, adding the drive letter (<B>DeviceID<\/B>) to the Dictionary, using the drive letter as both the Dictionary key and item.<\/P>\n<TABLE class=\"dataTable\" id=\"EUH\" 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>. We know, we know. But you can learn everything you\u2019d ever want to know about the Dictionary object \u2013 and then some \u2013 in everyone\u2019s favorite (well, <I>second<\/I> favorite) scripting column, <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/begin\/ss0906.mspx\"><B>Sesame Script<\/B><\/A>.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>When all is said and done, we\u2019ll have a Dictionary object containing keys similar to this, with each key representing a used drive letter:<\/P>\n<TABLE class=\"\" cellSpacing=\"0\" cellPadding=\"0\" border=\"0\">\n<TBODY>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>C:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>D:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>E:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>M:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>X:<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<P>And you\u2019re right: we still don\u2019t have a list of <I>available<\/I> drive letters, do we? But that\u2019s about to change, thanks to this block of code:<\/P><PRE class=\"codeSample\">For i = 67 to 90\n    strDrive = Chr(i) &amp; &#8220;:&#8221;\n    If objDictionary.Exists(strDrive) Then\n    Else\n        strDrives = strDrives &amp; strDrive &amp; vbCrLf\n    End If\nNext\n<\/PRE>\n<P>Don\u2019t worry; we were just about to explain how this works. To begin with, we set up a For Next loop that runs from 67 to 90. Why 67 to 90? Well, drive letters are limited to the letters C through Z (the letters A and B being reserved from floppy drives). As it turns out the <A href=\"http:\/\/www.asciitable.com\/\" target=\"_blank\"><B>ASCII value<\/B><\/A> for the letter C is 67, and the ASCII value for the letter Z is 90. Setting up a For Next loop that runs from 67 to 90 gives us a sneaky way to loop through all the letters from C through Z.<\/P>\n<P>Inside the For Next loop, we use the <B>Chr<\/B> function to convert the ASCII value of the loop variable (i) to an actual character; for example, the first time through the loop, i is equal to 67, which means that the Chr function will return the letter C. After converting the ASCII value we then tack a colon onto the end. That\u2019s what this line of code is for:<\/P><PRE class=\"codeSample\">strDrive = Chr(i) &amp; &#8220;:&#8221;\n<\/PRE>\n<P>In turn, that means that \u2013 the first time through the loop \u2013 the variable strDrive is equal to this: <B>C:<\/B>. <\/P>\n<P>Which, now that you mention it, <I>does<\/I> look an awful lot like a drive letter, doesn\u2019t it?<\/P>\n<P>That brings us to this line of code:<\/P><PRE class=\"codeSample\">If objDictionary.Exists(strDrive) Then\n<\/PRE>\n<P>Here we\u2019re using the <B>Exists<\/B> method to determine whether or not that first drive letter appears in the Dictionary object. Let\u2019s assume that it does. That means that the drive letter is already in use, and thus not available for drive mapping. Consequently, we don\u2019t do anything at all. (Well, other than circling around and repeating the process with the next value in the loop.) <\/P>\n<P>Now, suppose that the drive letter <I>can\u2019t<\/I> be found in the Dictionary. (That is, suppose the Exists method returns False.) That can only mean one thing: this drive letter is <I>not<\/I> in use, and thus <I>is<\/I> available for drive mapping. Consequently, we use this line of code to add the drive letter (and a carriage return-linefeed character) to a variable named strDrives:<\/P><PRE class=\"codeSample\">strDrives = strDrives &amp; strDrive &amp; vbCrLf\n<\/PRE>\n<P>Got that? By the time we exit the loop, all the available drive letters will be safely tucked away in the variable strDrives.<\/P>\n<P>Now all we have to do is figure out how to get those drive letters into our list box. To that end, our next step is to use the <B>Split<\/B> function to create an array named arrDrives; as you can see, we do this by splitting the variable strDrive on the carriage return-linefeed character (vbCrLf):<\/P><PRE class=\"codeSample\">arrDrives = Split(strDrives, vbCrlf)\n<\/PRE>\n<P>In turn, that gives us an array consisting of the following items (on our test computer), items that correspond quite nicely to the available drive letters on the computer:<\/P>\n<TABLE class=\"\" cellSpacing=\"0\" cellPadding=\"0\" border=\"0\">\n<TBODY>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>F:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>G:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>H:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>I:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>J:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>K:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>L:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>N:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>O:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>P:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>Q:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>R:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>S:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>T:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>U:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>V:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>W:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>Y:<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>Z:<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<P>And now \u2013 finally \u2013 we can add the available drive letters to the list box (and don\u2019t worry; the script zips by much quicker than the explanation does):<\/P><PRE class=\"codeSample\">For Each strDrive In arrDrives\n    Set objOption = Document.createElement(&#8220;OPTION&#8221;)\n    objOption.Text = strDrive\n    objOption.Value = strDrive\n    AvailableDrives.Add(objOption)\nNext\n<\/PRE>\n<P>All we\u2019ve done here set up a For Each loop to cycle through the collection of available drive letters. For each item in the collection we create an instance of the HTML Option object; each Option object is equivalent to an item in the list box. That\u2019s what this line of code is for:<\/P><PRE class=\"codeSample\">Set objOption = Document.createElement(&#8220;OPTION&#8221;)\n<\/PRE>\n<P>We then use these two lines of code to configure the <B>Text<\/B> and <B>Value<\/B> properties for the item:<\/P><PRE class=\"codeSample\">objOption.Text = strDrive\nobjOption.Value = strDrive\n<\/PRE>\n<P>If you haven\u2019t done a lot of work with HTML, the Text is simply the text that appears in the list box. The Value, meanwhile, is the data reported to a subroutine when a given option is chosen. Text and Value for an option do not <I>have<\/I> to be identical. We made them identical here simply because it makes sense: you want the drive letter to show up in the list box, and you probably want the exact same drive letter to be used in your subroutine.<\/P>\n<P>After configuring the Option object we add the new item to the list box like so:<\/P><PRE class=\"codeSample\">AvailableDrives.Add(objOption)\n<\/PRE>\n<P>As you can see, all we do is refer to the list box (AvailableDrives) and call the <B>Add<\/B> method. Along the way, we pass Add a single parameter: the object reference to our Option object. And then we loop around and repeat the process with the next item in the array. When <I>that\u2019s<\/I> finished, all the available drive letters will show up in a list box, a list box that should look something like this: <\/P><IMG height=\"204\" alt=\"Spacer\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/dynamiclist.jpg\" width=\"286\" border=\"0\"> \n<P>Now, what about that more-complete solution, the one that actually maps a drive for us? Well, without any further explanation, here\u2019s one way to do that. To use this HTA, select a drive letter, then click the <B>Map Drive<\/B> button. When the dialog box appears, type in the UNC path to the network drive (e.g., \\\\atl-fs-01\\public). Click <B>OK<\/B> and two things will happen:<\/P>\n<TABLE class=\"\" cellSpacing=\"0\" cellPadding=\"0\" border=\"0\">\n<TBODY>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>The drive will be mapped<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>The list box will refresh itself (because a previously-available drive letter is no longer available)<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<P>Here\u2019s the code:<\/P><PRE class=\"codeSample\">&lt;SCRIPT Language=&#8221;VBScript&#8221;&gt;\n    Sub Window_onLoad\n        Set objDictionary = CreateObject(&#8220;Scripting.Dictionary&#8221;)<\/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 colDisks = objWMIService.ExecQuery(&#8220;Select * from Win32_LogicalDisk&#8221;)<\/p>\n<p>        For Each objDisk in colDisks\n            objDictionary.Add objDisk.DeviceID, objDisk.DeviceID\n        Next<\/p>\n<p>        For i = 67 to 90\n            strDrive = Chr(i) &amp; &#8220;:&#8221;\n            If objDictionary.Exists(strDrive) Then\n            Else\n                strDrives = strDrives &amp; strDrive &amp; vbCrLf\n            End If\n        Next<\/p>\n<p>        arrDrives = Split(strDrives, vbCrlf)<\/p>\n<p>        For Each strDrive In arrDrives\n            Set objOption = Document.createElement(&#8220;OPTION&#8221;)\n            objOption.Text = strDrive\n            objOption.Value = strDrive\n            AvailableDrives.Add(objOption)\n        Next\n    End Sub<\/p>\n<p>    Sub MapDrive\n        If AvailableDrives.Value = &#8220;&#8221; Then\n            Msgbox &#8220;Please select a drive letter.&#8221;\n            Exit Sub\n        End If\n        strDrive = AvailableDrives.Value\n        strPath = InputBox(&#8220;Please enter the network path:&#8221;)\n        If strPath = &#8220;&#8221; Then\n            Exit Sub\n        End If\n        Set objNetwork = CreateObject(&#8220;Wscript.Network&#8221;)\n        objNetwork.MapNetworkDrive strDrive, strPath\n        Location.Reload(True)\n     End Sub\n&lt;\/SCRIPT&gt;<\/p>\n<p>&lt;body&gt;\n    &lt;select size=&#8221;5&#8243; name=&#8221;AvailableDrives&#8221; style=&#8221;width:100px&#8221;&gt;&lt;\/select&gt;&lt;p&gt;\n    &lt;input type=&#8221;button&#8221; value=&#8221;Map Drive&#8221; onClick=&#8221;MapDrive&#8221;&gt;\n&lt;\/body&gt;\n<\/PRE>\n<P>As for the Mariners, well, if anyone from the Seattle front office is reading this column (and, to be honest, we\u2019d really prefer that you were reading <I>Baseball Digest<\/I> instead) just send email to <A href=\"mailto:scripter@microsoft.com\"><B>scripter@microsoft.com (in English, if possible)<\/B><\/A> and make us an offer. We can\u2019t promise to accept that offer; why that would mean giving up a thrilling and rewarding career as a technical writer just for the chance to fly around the country playing baseball. But we\u2019ll definitely take it under consideration.<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I\u2019m using an HTA as a drive-mapping application. I\u2019d like to be clever about this and have the available drive letters appear in a list box. How can I dynamically show all the drive letters available on a computer?&#8212; JT Hey, JT. You know, just the other day the Scripting Guy who [&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,4,185,12,5,30],"class_list":["post-63973","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-scripting-guy","tag-scripting-techniques","tag-shared-folders-and-mapped-drives","tag-storage","tag-vbscript","tag-web-pages-and-htas"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I\u2019m using an HTA as a drive-mapping application. I\u2019d like to be clever about this and have the available drive letters appear in a list box. How can I dynamically show all the drive letters available on a computer?&#8212; JT Hey, JT. You know, just the other day the Scripting Guy who [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/63973","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=63973"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/63973\/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=63973"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=63973"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=63973"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}