{"id":67973,"date":"2006-02-13T04:51:00","date_gmt":"2006-02-13T04:51:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2006\/02\/13\/how-can-i-determine-when-a-removable-drive-gets-connected\/"},"modified":"2006-02-13T04:51:00","modified_gmt":"2006-02-13T04:51:00","slug":"how-can-i-determine-when-a-removable-drive-gets-connected","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-determine-when-a-removable-drive-gets-connected\/","title":{"rendered":"How Can I Determine When a Removable Drive Gets Connected?"},"content":{"rendered":"<p><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\"> \n<P>Hey, Scripting Guy! How can I determine when a USB flash drive gets connected?<BR><BR>&#8212; PS<\/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, PS. OK, we admit it: the Scripting Guys are lazy. (Especially on a Friday, which is the day when we have to write our Monday column.) There might be a way to monitor specifically for the insertion of a USB flash drive; however, we couldn\u2019t find one, at least not right away. Admittedly, we probably <I>could<\/I> have looked a bit harder; however, we decided instead to write a script that tells you when <I>any<\/I> removable drive gets connected (or disconnected) from a machine. We like to think that this way we\u2019re providing you with additional value and flexibility.<\/P>\n<P>Hey, we didn\u2019t say we really <I>were<\/I> providing you with additional value and flexibility. We just like to think that we are.<\/P>\n<P>Actually, this is kind of a handy little script. And it has the added benefit of running on any version of Windows. (Originally we toyed with the notion of using the Win32_VolumeChangeEvent class to accomplish this task, but that particular WMI class is found only on Windows XP or greater.)<\/P>\n<P>Here\u2019s what the code looks like:<\/P><PRE class=\"codeSample\">strComputer = &#8220;.&#8221;\nSet objWMIService = GetObject(&#8220;winmgmts:\\\\&#8221; &amp; strComputer &amp; &#8220;\\root\\cimv2&#8221;)<\/p>\n<p>Set colEvents = objWMIService.ExecNotificationQuery _\n    (&#8220;Select * From __InstanceOperationEvent Within 10 Where &#8221; _\n        &amp; &#8220;TargetInstance isa &#8216;Win32_LogicalDisk'&#8221;)<\/p>\n<p>Do While True\n    Set objEvent = colEvents.NextEvent\n    If objEvent.TargetInstance.DriveType = 2 Then \n        Select Case objEvent.Path_.Class\n            Case &#8220;__InstanceCreationEvent&#8221;\n                Wscript.Echo &#8220;Drive &#8221; &amp; objEvent.TargetInstance.DeviceId &amp; _\n                    &#8221; has been added.&#8221;\n            Case &#8220;__InstanceDeletionEvent&#8221;\n                Wscript.Echo &#8220;Drive &#8221; &amp; objEvent.TargetInstance.DeviceId &amp; _\n                    &#8221; has been removed.&#8221;\n        End Select\n    End If\nLoop\n<\/PRE>\n<P>And yes, this <I>is<\/I> similar to the <A href=\"http:\/\/null\/technet\/scriptcenter\/resources\/qanda\/feb06\/hey0210.mspx\"><B>screensaver monitoring script<\/B><\/A> we showed you the other day. We like to think that reusing the same script day-after-day provides you with additional value and flexibility. (Although mostly it just ensures that we don\u2019t have to work very hard.) <\/P>\n<P>This script starts off by connecting to the WMI service on the local computer. We then issue this query:<\/P><PRE class=\"codeSample\">Set colEvents = objWMIService.ExecNotificationQuery _\n    (&#8220;Select * From __InstanceOperationEvent Within 10 Where &#8221; _\n        &amp; &#8220;TargetInstance ISA &#8216;Win32_LogicalDisk'&#8221;)\n<\/PRE>\n<P>What\u2019s going on here? Well, here we\u2019re using the <B>ExecNotificationQuery<\/B> method to subscribe to a particular set of WMI events. What WMI events? (Boy, you have a lot of questions, don\u2019t you?) In this case we want to be notified any time changes are made to an instance of the Win32_LogicalDisk class; as you\u2019ll see momentarily, those changes will include creating a new instance of the class (i.e., adding a removable drive) and deleting an existing instance of the class (i.e., removing a removable drive). The <B>Within 10<\/B> simply means we\u2019re going to check every 10 seconds to see whether any of the Win32_LogicalDisk instances have changed. <\/P>\n<P>And yes, that means if you insert a removable drive and then remove it 6 seconds later we might never know about it. If that\u2019s a problem, then change 10 to a smaller number. You can also change 10 to a higher number. For example, change 10 to 60 and your check will occur every 60 seconds rather than every 10 seconds.<\/P>\n<P>See? We even built added value and flexibility into the code itself!<\/P>\n<P>After that we set up one of those crazy Do loops designed to run forever:<\/P><PRE class=\"codeSample\">Do While True\n<\/PRE>\n<P>And then we encounter this line of code:<\/P><PRE class=\"codeSample\">Set objEvent = colEvents.NextEvent\n<\/PRE>\n<P>As we noted in the <A href=\"http:\/\/null\/technet\/scriptcenter\/resources\/qanda\/feb06\/hey0210.mspx\"><B>previous column<\/B><\/A>, this line of code causes the script to \u201cblock;\u201d that simply means the script will pause on this line until there\u2019s a change to the Win32_LogicalDisk class. That change (which could be the creation of a new instance or the deletion\/modification of an existing instance) will then cause the script to execute the remaining lines of code in the Do loop.<\/P>\n<P>Good question: what exactly <I>do<\/I> those remaining lines of code do? Well, first we check to see if the drive that generated the event happens to be a removable drive (a <B>DriveType<\/B> of 2 as far as WMI is concerned):<\/P><PRE class=\"codeSample\">If objEvent.TargetInstance.DriveType = 2 Then\n<\/PRE>\n<P>If the DriveType is <I>not<\/I> 2, then we just loop around and wait for the next event to occur. If the DriveType <I>is<\/I> 2 then we use a Select Case block to determine which type of event occurred. We can do that by determining the <B>Class<\/B> of the event:<\/P><PRE class=\"codeSample\">Select Case objEvent.Path_.Class\n<\/PRE>\n<P>Why do we do that? Two reasons: First, we aren\u2019t interested in any changes to existing instances. For example, we don\u2019t care if the amount of free drive space has changed on drive C. If you look at the Select Case code you\u2019ll notice we don\u2019t bother checking for the __InstanceModificationEvent. Why not? Because we don\u2019t care about the __InstanceModificationEvent (the event type generated when an existing instance is modified in some way).<\/P>\n<P>Second, we want to draw a distinction between the __InstanceCreationEvent (which tells us a new drive has been created) and the __InstanceDeletionEvent (which tells us an existing drive has been deleted). By identifying the event type we can echo back a different (and appropriate) message. For example, here\u2019s the code that determines whether a new drive was created and, if so, echoes back a message to that effect:<\/P><PRE class=\"codeSample\">Case &#8220;__InstanceCreationEvent&#8221;\n    Wscript.Echo &#8220;Drive &#8221; &amp; objEvent.TargetInstance.DeviceId &amp; _\n        &#8221; has been added.&#8221;\n<\/PRE>\n<P>And here\u2019s the code that tells us whether an existing drive has been deleted:<\/P><PRE class=\"codeSample\">Case &#8220;__InstanceDeletionEvent&#8221;\n    Wscript.Echo &#8220;Drive &#8221; &amp; objEvent.TargetInstance.DeviceId &amp; _\n        &#8221; has been removed.&#8221;\n<\/PRE>\n<P>Once we\u2019ve echoed the appropriate message we loop around and wait for the next event to occur. By default the script will run forever, or at least until you terminate the script process. Whichever comes first.<\/P>\n<P>Like we said, it\u2019s not <I>exactly<\/I> what you asked for, but it should do the job. Oh, and don\u2019t forget the additional value and flexibility. That should more than make up for the fact that we didn\u2019t really answer your question. (We like to think we answered <I>a<\/I> question. Just not your question.)<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I determine when a USB flash drive gets connected?&#8212; PS Hey, PS. OK, we admit it: the Scripting Guys are lazy. (Especially on a Friday, which is the day when we have to write our Monday column.) There might be a way to monitor specifically for the insertion of a [&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,42,3,4,12,5,6],"class_list":["post-67973","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-disk-drives-and-volumes","tag-events-and-monitoring","tag-scripting-guy","tag-scripting-techniques","tag-storage","tag-vbscript","tag-wmi"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I determine when a USB flash drive gets connected?&#8212; PS Hey, PS. OK, we admit it: the Scripting Guys are lazy. (Especially on a Friday, which is the day when we have to write our Monday column.) There might be a way to monitor specifically for the insertion of a [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/67973","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=67973"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/67973\/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=67973"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=67973"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=67973"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}