Hey, Scripting Guy! How Can I Be Notified When a USB Drive Is Plugged into My Computer?

Hey, Scripting Guy! How Can I Be Notified When a USB Drive Is Plugged into My Computer?

  • Comments 1
  • Likes

Bookmark and Share


Hey, Scripting Guy! Question

Hey, Scripting Guy! I would like to be notified when I plug in a USB drive into my computer. I have some cool ideas for using that, but I do not know how to detect when a USB drive is plugged in. I know I can run a script that loops through looking for all drives, and compares them with a previous collection of drives and then looks for differences. I also know I can use the Compare-Object cmdlet to make the comparison, so it would not be too terribly hard, but it seems inefficient. Is there a better way to do this?

-- SP


Hey, Scripting Guy! AnswerHello SP,

Microsoft Scripting Guy Ed Wilson here. We are getting closer and closer to the 2010 Scripting Games. They begin on April 26 and will run for two weeks. Registration has been open for a week or so, and we encourage you to sign up. It takes less than a minute because you can use your Windows Live ID. Craig has rounded up some really cool prizes (Scripting Editor: I don’t know who this Craig guy is, but he sounds really awesome), and some of the Windows PowerShell user groups are even offering additional prizes for their members who participate.

SP, what you need to do is investigate WMI events. We have lots of Hey, Scripting Guy! Blog posts that talk about using WMI events from within VBScript. We also have several Hey, Scripting Guy! posts that deal with WMI events from Windows PowerShell.

There are two types of WMI event classes that can be used. The first are intrinsic event classes, which are WMI classes that are designed to monitor for events. All these classes do is monitor for WMI events. An example of an intrinsic WMI event class is Win32_ProcessStartTrace. Because this is an intrinsic WMI class, you cannot use the Get-WmiObject (gwmi alias) cmdlet and pass the WMI class to the Get-Member (gm alias) cmdlet and see its properties and methods. An error is generated that states that no object has been supplied to the Get-Member cmdlet. This is true because the Win32_ProcessStartTrace WMI class is created when a new process is generated and WMI is configured to watch for new processes to start up.

PS C:\> gwmi win32_processStartTrace | gm
Get-Member : No object has been specified to the Get-Member cmdlet.
At line:1 char:34
+ gwmi win32_processStartTrace | gm <<<<
    + CategoryInfo          : CloseError: (:) [Get-Member], InvalidOperationException
    + FullyQualifiedErrorId : NoObjectInGetMember,Microsoft.PowerShell.Commands.GetMemberCommand

PS C:\>

To use a “regular” WMI class to monitor for WMI events, it is necessary to use a generic WMI event class such as __InstanceCreationEvent. The thing that is cool about using the __InstanceCreationEvent WMI class is that it returns a complete copy of the WMI object that created the event. This allows you to obtain a lot of very useful information about the event. To use the __InstanceCreationEvent WMI class, it is necessary to compose an “event query.” You can do this by typing directly into the –query property of the Windows PowerShell console. The following is a single-line command that is wrapped onto two lines. To avoid confusion, I did not break it into two separate lines, nor did I close and open extra quotation marks and use line continuation. If you cut and paste the command, please ensure you have one line of code by either pasting it in Notepad and cleaning it up, or in the Windows PowerShell ISE before running the command:

Register-WmiEvent -Query "Select * from __InstanceCreationEvent within 5 where targetinstance isa 'win32_logicaldisk'" -SourceIdentifier disk -Timeout 1000

When you run the command, nothing is returned and nothing appears to have happened. When a USB drive is plugged into the computer, still nothing appears to happen. However, if you want to retrieve the event that was returned, use the Get-Event cmdlet as seen here:

PS C:\> Get-Event -SourceIdentifier disk

ComputerName     :
RunspaceId       : 1564db50-15ae-4970-8ad3-d759d3092d96
EventIdentifier  : 1
Sender           : System.Management.ManagementEventWatcher
SourceEventArgs  : System.Management.EventArrivedEventArgs
SourceArgs       : {System.Management.ManagementEventWatcher, System.Management.EventArrivedEventArgs}
SourceIdentifier : disk
TimeGenerated    : 4/9/2010 12:10:16 PM
MessageData      :

The information that is returned by the Get-Event cmdlet is less than illuminating. But this is only because it returns several different objects. To find information about the newly inserted drive, store the object in a variable:

$a = Get-Event -SourceIdentifier disk

Once you have the object stored in a variable, it is easy to query the TargetInstance from the NewEvent object. This is seen here:


When you run these commands, you receive the output shown in the following image.

Image of output of running the commands


SP, that is all there is to using WMI events. WMI Week will continue tomorrow.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.


Ed Wilson and Craig Liebendorfer, Scripting Guys


Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • You can find all related classes with this command.

    Get-WmiObject -list | where {$_.name -match "__instance" -and "event"}