{"id":56063,"date":"2008-03-05T23:58:00","date_gmt":"2008-03-05T23:58:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2008\/03\/05\/hey-scripting-guy-how-can-i-verify-that-a-user-entered-a-valid-drive-letter\/"},"modified":"2008-03-05T23:58:00","modified_gmt":"2008-03-05T23:58:00","slug":"hey-scripting-guy-how-can-i-verify-that-a-user-entered-a-valid-drive-letter","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-verify-that-a-user-entered-a-valid-drive-letter\/","title":{"rendered":"Hey, Scripting Guy! How Can I Verify That a User Entered a Valid Drive Letter?"},"content":{"rendered":"<p><img decoding=\"async\" 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\" \/> <\/p>\n<p>Hey, Scripting Guy! How can I make sure that data entered into an InputBox has the form <b>X:<\/b>, where X is any alphabetic character? That\u2019s important, because I need to use this string to map logical drives in a script. The script should validate any string such as D:, E:, or F: but flag as incorrect any string such as 9:, !:, 22: etc. I have had limited exposure to regular expressions, and I just can&#8217;t seem to get the correct pattern.<\/p>\n<p>&#8212; DL<\/p>\n<p><img decoding=\"async\" height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\" \/><img decoding=\"async\" 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 decoding=\"async\" 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> <\/p>\n<p>Hey, DL. If you want to know the truth, there are days when the Scripting Guy who writes this column doesn\u2019t always feel like writing this column. (Shocked? Don\u2019t be; the Scripting Guys have all <i>sorts<\/i> of deep, dark secrets like that one.) Today isn\u2019t one of those days, however. On the contrary, today the Scripting Guy who writes this column was happy to take time out to write about validating data entered into an input box. That\u2019s because his alternative would be to return to playing Blackjack. And after playing more than 200 hands of Blackjack this morning, he needed a break.<\/p>\n<table class=\"dataTable\" id=\"ECD\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p><b>Note<\/b>. If you\u2019re one of those people who can go to a casino and sit there all day or all night playing cards, well, the Scripting Guy who writes this column tips his hat to you; he couldn\u2019t do it. Instead, after 30 or 40 hands (or was it 130 or 140?) the Scripting Guy who writes this column was ready to throw in the towel.<\/p>\n<p>Of course, unlike an actual casino, there weren\u2019t any waitresses walking around his office bringing him free drinks, either. We suppose that <i>could<\/i> make a difference.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>Of course, many of you are probably thinking, \u201cWhy is he playing Blackjack? Is the Scripting Editor running an illegal gambling ring out of her office?\u201d Well, as a matter of fact, she is. However, she won\u2019t let the Scripting Guy who writes this column go in there; instead she just calls the bouncer, all the while muttering something about keeping out the riff-raff. (Which doesn\u2019t make much sense; after all, she lets Peter and Dean go in there.)<\/p>\n<p>Instead, the Scripting Guy who writes this column was simply scoring <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/funzone\/games\/games08\/aevent10.mspx\"><b>Event 10<\/b><\/a> in the 2008 Winter Scripting Games (Advanced Division), an event that required competitors to write a script that could play a hand of Blackjack.<\/p>\n<table class=\"dataTable\" id=\"E2D\" 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>. If you\u2019re torn between entering the actual Winter or Summer Olympics or the 2009 Winter Scripting Games, we might note that, in the Scripting Games, you get to do things like play Blackjack. In the Olympics, you get to do things like run a marathon. It\u2019s up to you.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>At any rate, for all you Scripting Gamers anxious to see your final scores, well, we\u2019re getting there; for that matter, we might even <i>be<\/i> there by the time you read this column. In fact, we\u2019re close enough now that we figured we could take time out to show everyone how to verify that a valid drive letter was entered into an input box:<\/p>\n<pre class=\"codeSample\">Set objRegEx = CreateObject(\"VBScript.RegExp\")\n\nobjRegEx.Global = True   \nobjRegEx.Pattern = \"[d-zD-Z]:\"\n\nDo While True\n    strSearchString = InputBox(\"Please enter the drive letter:\", \"Drive Letter\")\n\n    If strSearchString = \"\" Then\n        Wscript.Quit\n    End If\n\n    If Len(strSearchString) = 2 Then\n        Set colMatches = objRegEx.Execute(strSearchString)  \n\n        If colMatches.Count &gt; 0 Then\n            Exit Do\n        End If\n    End If\nLoop\n\nWscript.Echo \"Your drive letter is \" &amp; strSearchString &amp; \".\"\n<\/pre>\n<p>Let\u2019s see if we can figure out what\u2019s going on here. (With the Scripting Guys, that\u2019s almost <i>always<\/i> a good question.) We start out by creating an instance of the <b>VBScript.RegExp<\/b> object; this is the object that enables us to use regular expressions within a VBScript script. After creating an instance of RegExp we assign values to two of the object\u2019s properties. For one, we set the <b>Global<\/b> property to True; this tells the script that we want to search for all instances of the target text. In this case, the Global property doesn\u2019t really matter; there will be, at most, only one match (that is, one drive letter) for us to find anyway. In general, though, setting Global to True is a good thing; usually you want to find all the instances of something, not just the first instance. <\/p>\n<p>Our next property, <b>Pattern<\/b>, is a little more interesting. (Although we aren\u2019t saying that the Global property <i>isn\u2019t<\/i> interesting. We would <i>never<\/i> say a thing like that!) The Pattern property is where we specify the text we want to find. What text <i>do<\/i> we want to find? This:<\/p>\n<pre class=\"codeSample\">\"[d-zD-Z]:\"\n<\/pre>\n<p>We won\u2019t go through the ins and outs of regular expression syntax in today\u2019s column; for an introduction to regular expressions you might take a peek at our <a href=\"http:\/\/technet.microsoft.com\/en-us\/magazine\/cc137729.aspx\" target=\"_blank\"><b>TechNet Magazine<\/b><\/a> column on the subject. In a nutshell, this regular expression can be parsed like so: First, find <i>any<\/i> of the characters specified within the square brackets (<b>[ ]<\/b>). Square brackets allow you to specify a set of characters; if any one of those characters is found then you have a match.<\/p>\n<p>So what characters <i>are<\/i> we looking for? Well, it could be any character in the range <b>d-z<\/b>.; that\u2019s all the lowercase letters from <i>d<\/i> to <i>z<\/i>. Alternatively, it could be any character in the range <b>D-Z<\/b>; that\u2019s all the uppercase characters from <i>D<\/i> to <i>Z<\/i>. P, Q, R, s, t, and u would all results in matches; A, B, and c would not.<\/p>\n<table class=\"dataTable\" id=\"ELG\" 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>. Why D through Z (or d through z)? That\u2019s easy: you can\u2019t map drives using the letters A, B, or C (or their lowercase equivalents).<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>In other words, the first character must be a letter (uppercase or lowercase) from D to Z. That letter must then be followed by a colon (that\u2019s what the <b>:<\/b> is for). As DL wished, D:, E:, and, F: will be considered valid input; 9:, !:, and 22: will not.<\/p>\n<p>After defining our regular expression pattern we next set up a Do loop designed to run forever and ever. (Or at least as long as True is equal to True.) Inside that loop, the first thing we do is use this line of code to display an input box that prompts the user to enter a drive letter:<\/p>\n<pre class=\"codeSample\">strSearchString = InputBox(\"Please enter the drive letter:\", \"Drive Letter\")\n<\/pre>\n<p>The input box will remain onscreen until the user clicks either the <b>OK<\/b> button or the <b>Cancel<\/b> button. If the user clicks <b>OK<\/b>, the value he or she typed into the box will be stored in a variable we named strSearchString. If the user clicks <b>Cancel<\/b>, then strSearchString will be set to an empty string.<\/p>\n<p>Suppose the user <i>does<\/i> click <b>Cancel<\/b>. In that case, we\u2019re assuming that they don\u2019t want to map a drive after all. With that in mind, we use this block of code to see if strSearchString is equal to an empty string; if it is, we then call the <b>Wscript.Quit<\/b> method to terminate the script:<\/p>\n<pre class=\"codeSample\">If strSearchString = \"\" Then\n    Wscript.Quit\nEnd If\n<\/pre>\n<p>If strSearchString is <i>not<\/i> empty our next task is to make sure that there are only two characters in the string (you can\u2019t map a drive to, say, drive ABCDE:). Although we could have created a more-complicated regular expression to check for string length we thought it would be easier to just let VBScript\u2019s <b>Len<\/b> function take care of it for us:<\/p>\n<pre class=\"codeSample\">If Len(strSearchString) = 2 Then\n<\/pre>\n<p>If the string length (number of characters) is anything other than 2 we\u2019re simply going to loop around, display another input box, and prompt the user to try again. If the string length <i>is<\/i> 2, however, then we use this line of code to actually perform our regular expression search:<\/p>\n<pre class=\"codeSample\">Set colMatches = objRegEx.Execute(strSearchString)\n<\/pre>\n<p>If any instances of the target text (that is, one of the letters D through Z, followed by a colon) are found then those instances are stored in a collection we named colMatches. How are we supposed to know if any matches <i>were<\/i> found? That\u2019s easy; we just check the <b>Count<\/b> property, which tells us the number of items in the collection:<\/p>\n<pre class=\"codeSample\">If colMatches.Count &gt; 0 Then\n<\/pre>\n<p>If the Count is greater than 0 that means we have a valid drive letter; in that case, we call the <b>Exit Do <\/b>statement to exit our Do loop. We then simply echo back the drive letter:<\/p>\n<pre class=\"codeSample\">Wscript.Echo \"Your drive letter is \" &amp; strSearchString &amp; \".\"\n<\/pre>\n<p>If the Count <i>equals<\/i> 0 that means the \u201cdrive letter\u201d that was entered was invalid; for example, maybe the user entered $:. If that\u2019s the case we again go back to the top of the loop, display another input box, and try the whole thing all over again.<\/p>\n<p>Believe it or not, that\u2019s all there is to it.<\/p>\n<p>In case you\u2019re wondering, the Scripting Guy who writes this column didn\u2019t keep track of his Blackjack wins and losses. He actually started to do that, but after he lost 6 of the first 8 games he figured that was silly.<\/p>\n<p>Although, come to think of it, maybe that wasn\u2019t his fault; maybe those scripts were all poorly-written. Sure, that must be it: the Scripting Guy who writes this column didn\u2019t fail, the <i>scripts<\/i> failed. You know what? We\u2019ll see everyone tomorrow, right now we have to go back and change a bunch of 10s to 0s.<\/p>\n<table class=\"dataTable\" id=\"ECBAC\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p class=\"lastInCell\"><b>Note to Scripting Games competitors<\/b>. Take it easy; we\u2019re just <i>joking<\/i>.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I make sure that data entered into an InputBox has the form X:, where X is any alphabetic character? That\u2019s important, because I need to use this string to map logical drives in a script. The script should validate any string such as D:, E:, or F: but flag as [&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":[216,174,3,4,12,5],"class_list":["post-56063","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-disk-drives-and-volumes","tag-regular-expressions","tag-scripting-guy","tag-scripting-techniques","tag-storage","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I make sure that data entered into an InputBox has the form X:, where X is any alphabetic character? That\u2019s important, because I need to use this string to map logical drives in a script. The script should validate any string such as D:, E:, or F: but flag as [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/56063","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=56063"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/56063\/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=56063"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=56063"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=56063"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}