in reply to Re^2: How do I know when a USB device is inserted?
in thread How do I know when a USB device is inserted?

Here's a working example:

#!perl -w use strict; use Win32::GUI (); use constant WM_DEVICECHANGE => 0x219; # as per http://msdn.microsoft.com/en-us/library/aa363480%28VS.85%29.a +spx sub device_changed { my ($win, @args) = @_; Win32::GUI::MessageBox(0,"Device changed: @args\n"); }; my $mw = Win32::GUI::Window->new(); $mw->Hook(WM_DEVICECHANGE, \&device_changed); $mw->Show(); Win32::GUI::Dialog(); print "Done\n";

A problem with this approach is that WM_DEVICECHANGE does not seem to fire if AutoPlay is disabled for devices, at least I don't get the message when I insert a CF card in my CF card reader, while I get the message when I plug/unplug some other device.

Replies are listed 'Best First'.
Re^4: How do I know when a USB device is inserted?
by ZJ.Mike.2009 (Scribe) on Mar 06, 2010 at 09:40 UTC

    Corian, Thank you again :) I'm very happy to have a convenient GUI example.

    I was playing around with DBD::WMI. This module looks very nice. Well, let me say before asking this question, I had actually googled with the query term combinations like "Perl USB" and "Perl Device Change" but nothing strictly relevant came up. And, well, it's awesome to have all the ready example here :) Thank you!

    BTW, I got the following script to detect an USB insertion event. And I'm having some trouble retrieving the volume name of the USB. I was wondering if there's a convenient way to retrieve the volume letter of the inserted USB device? Maybe I'm asking too much :) Thanks anyway!

    use DBI; my $dbh = DBI->connect('dbi:WMI:'); my $sth = $dbh->prepare(<<WQL); Select * From __InstanceCreationEvent Within 1 Where TargetInstance Isa 'Win32_DiskDrive' And TargetInstance.InterfaceType = 'USB' WQL $sth->execute(); while (my @row = $sth->fetchrow) { my $proc = $row->[0]; print "USB inserted\n"; }

      I thought I had such a program in the DBD::WMI distribution, but I didn't. I've added the following example to (the next release of) DBD::WMI, and it works and tells me the added/removed drive letter:

      #!/usr/bin/perl -w package main; use strict; use DBI; use Data::Dumper; my $dbh = DBI->connect('dbi:WMI:'); my $sth = $dbh->prepare(<<WQL); SELECT * FROM __instanceoperationevent WITHIN 5 WHERE TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.Name != 'C:' WQL $sth->execute(); # loops forever while (defined (my $row = $sth->fetchrow_arrayref())) { my $ev = $row->[0]; # Windows XP only :( print "Class\t",$ev->Path_->Class,"\n"; for (qw(Name DeviceID Caption MediaType InterfaceType)) { print join "\t", $_, ($ev->TargetInstance->{$_} || '<none>'); print "\n"; if ($ev->Path_->Class eq '__InstanceCreationEvent') { print "Device (letter) $ev->{TargetInstance}->{Name} added +\n"; } } }

      The restriction on .InterfaceType to "USB" does not work, because the Win32_LogicalDisk does not have that property, unfortunately. So you'll have to hope that the added drive letter actually corresponds to the/a USB drive.

        Great! Thanks, Corian! The code works like charm :)

        Just a small itsy bitsy problem with one of my USB flash disks but that is because that USB device has two partitions, one as a fake, an emulated bootable CD-ROM and the other as a normal USB flash partition. But it generally works like charm! Thanks, Corian, I really appreciate your help. DBD::WMI is awesome. I like it :)