Jump to content


Detecting USB Drive Insertion

  • Please log in to reply
10 replies to this topic

#1 SkinnyWhiteGuy


    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 10 March 2007 - 12:25 AM

Hello all, I've recently gotten into AutoIt, and so far, I love it. All those old hacks and tricks I used to do with BAT files are now trivial, and I'm on to bigger and better things. That being said, I have a slight problem.

My latest project involves USB Drives. I am trying to write a script that, while running on the computer, can detect when a USB drive is inserted, and automatically backup my files off of it (given the Label matches). I've gotten a good bit of the code figured out, but I'm stuck. I was wondering if anyone could help me.

Here's the code I have so far:

$DBT_DEVICEARRIVAL = "0x00008000" $WM_DEVICECHANGE = 0x0219 GUICreate("") GUIRegisterMsg($WM_DEVICECHANGE , "MyFunc") Func MyFunc($hWndGUI, $MsgID, $WParam, $LParam)     If $WParam == $DBT_DEVICEARRIVAL Then     ; Find newly inserted Drive here, test for correct label, and then backup files from it     EndIf EndFunc While 1     $GuiMsg = GUIGetMsg() WEnd

It can successfully detect whenever a new Device is inserted into the computer just fine, there's just 2 problems with it so far:
1. It can't tell the difference between a newly inserted CD and a newly inserted USB drive, which is not good, as I would like for it to only trigger on USBs
2. Even though it can detect that something was inserted, it can't find the drive in question (by Letter, I mean). I could make a function that, whenever something was inserted, compare it to a list of drives before the insertion, and the difference has to be my new drive, but that's ugly, and also means I'd have to investigate as to detecting when drives were removed to keep my list clean.

From all of my readings and Googling, all I can come up with is that the $LParam has something to do with what kind of drive is being inserted, and where it might be located (as per this article). But, I can't seem to detect the differences with what I have so far.

If anyone can help me, I would greatly appreciate it. Thanks for any help you provide me.

#2 smashly


  • Active Members
  • PipPipPipPipPipPip
  • 1,636 posts

Posted 10 March 2007 - 04:07 AM

Sorry I don't have answer to you question , but I'd just like to say thank you for your function :whistle:

This was just what I was looking for.

I use your function to detect when my psp is plugged in and sharing it's flash memory so it auto updates my modified files to the flash.

For me to check that your function has the correct drive I'm using a sloppy approach , but it works all the same.
I use
DriveGetDrive() to list the drives available

DriveGetType() to get the type of drive ("REMOVABLE" is what I'm after)

$DBT_DEVICEARRIVAL = "0x00008000" $WM_DEVICECHANGE = 0x0219 GUICreate("") GUIRegisterMsg($WM_DEVICECHANGE , "MyFunc") Func MyFunc($hWndGUI, $MsgID, $WParam, $LParam)     If $WParam == $DBT_DEVICEARRIVAL Then     $dg = DriveGetDrive( "REMOVABLE" )         For $i = 1 to $dg[0]             $dt = DriveGetType( $dg[$i] )             If $dt = "REMOVABLE" And $dg[$i] <> "a:" And $dg[$i] <> "b:" Then                 ;;look for my marker file at $dg[$i] , if found do check...                 MsgBox(4096,"Drive " & $i, $dg[$i] & " = " & $dt)             EndIf         Next     EndIf EndFunc While 1     $GuiMsg = GUIGetMsg() WEnd

If removable drive is found then I look for a unique marker file on the removable drive that I have an MD5 for and compare.
If the removable drive has this correct marker file then I know it's the drive I'm looking for.

If there is no marker file on the removable drive then check the next removable drive and ... so on

Once I have the correct drive I then do a file compare from my update archive on the pc with the plugged in psp flash memory...
If there are differences in the files on the pc and psp (md5 check all files compare), time stamp is newer and psp flash has enough space then they are transfered to the psp flash memory.
Must admit I'm still trying to quash some minor bugs in my script, method is crude but works for my needs.

Thank You

Edited by smashly, 10 March 2007 - 05:09 AM.

#3 SkinnyWhiteGuy


    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 10 March 2007 - 04:35 AM

Well, I did some more work on it, and did manage to get it to tell the difference between a CD insertion and USB, though it's a crude hack at best. It ends up using the Drive Removal Event, too, so I may end up just hacking it all together without using the LParam, but I have a very strong feeling there's an easier way to do all this than I'm seeing. I can't post it this weekend. It's on my computer at work, so I'll try to post it Monday.

@Smashly: Glad I could be of some assistance, and I think I can help you even more. The DriveGetDrive your using supports "REMOVABLE" as an argument, so that next step you were doing to test for removable can be skipped by just using that arguement.

#4 smashly


  • Active Members
  • PipPipPipPipPipPip
  • 1,636 posts

Posted 10 March 2007 - 04:42 AM

Yep the "REMOVABLE" argument is what I use , but most times I have multiple removable drives on my PC..
Even a: or b: drives are classed as removable. this is why I exclude a: and b: and check for more then 1 removable drive against a marker file. edited my post above with what I mean.


Edit I see what you mean , use DriveGetDrive for "removable" drives only.

But the funny thing is if I have a removable drive already plugged in and I put a cdrom in the drive then it invokes the script again, not really a problem as the script still sees the correct removable drive. just a quirk you could say... lol

Edited by smashly, 10 March 2007 - 05:07 AM.

#5 SkinnyWhiteGuy


    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 10 March 2007 - 05:59 AM

I know, any media insertion will trigger the script I gave here (even floppy, if I'm not mistaken. Haven't tested).

I've done a good bit more digging, and come up with something that's both promising and disconcerting:

Latest Find

This version of basically what I want to do uses VB and the WMI, both of which AutoIt supports wonderfully. I've used WMI ScriptOMatic and seen what things I'd need to do some of what that page shows, but some parts still elude me.

While all this is very promising, I can't figure it out, and I have a sinking feeling that the original code I wrote, while interesting, may be thrown out in favor of this new found code, given I, or someone else on here, can figure out what this new script does, and how to get AutoIt to do it too.

As a side note, I also realized another use for this script (if you purposefully searched for CD-ROMS): Auto-Ripping of Audio Tracks from each Audio CD you inserted without having to run the program more than once, just have this type of event trigger another script to start the ripping. Hopefully, something like this could make digitizing someone's collection a lot easier.

#6 SkinnyWhiteGuy


    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 11 March 2007 - 12:00 AM

Well, I got bored last night/today. Read a whole lot of info, discovered how to read the data from LParam (a struct), then discovered that it too held the same data no matter if I inserted a CD or a USB drive. So, I fought with it, kept trying, couldn't make heads or tails of it that way. I still don't understand near enough about the WMI, especially how to register the event watcher for it, so, I went the ugly route. I give you the USB Backup Script, that, while active, will watch for any inserted drives, and once it detects that the drive is the one you configured, has space to backup specific folders as you wish (I left that part up to anyone else to fill in). Here it is:

Plain Text         
Dim $DBT_DEVICEARRIVAL = "0x00008000" Dim $DBT_DEVICECOMPLETEREMOVAL = "0x00008004" Dim $USB_ATTENTION = "0x00000007" Dim $WM_DEVICECHANGE = 0x0219 Dim $Drives Dim $Drive_Type = "ALL"  ; Set to ALL because some USB Drives are detected as Fixed Disks, and we don't want to miss those Dim $WATCH = False Dim $MyDrive = "STUFF" ;Get Initial List of Drives to Check Against UpdateDrives() ;Setup The GUI to watch for the DeviceChange Event GUICreate("") GUIRegisterMsg($WM_DEVICECHANGE, "DeviceChange") Func DeviceChange($hWndGUI, $MsgID, $WParam, $LParam)     Switch $WParam         Case $USB_ATTENTION         ; This only happens when USB drives are inserted, so I use it to tell the difference between these and CDROMs             $WATCH = True         Case $DBT_DEVICECOMPLETEREMOVAL         ; Whenever a Drive is Removed, Update the Drive List             UpdateDrives()         Case $DBT_DEVICEARRIVAL         ; A drive was inserted         ; Use $WATCH to tell if this was a CDROM or USB         ; $WATCH = True, USB         ; $WATCH = False, CDROM             If $WATCH = True Then             ; New USB Drive Was Detected, Time to Find it's Letter                 $New = FindNewDrive(); $New now has the Drive Letter of our New Drive, so USE IT!!!                 $Label = DriveGetLabel($New)                 If $Label == $MyDrive Then                     MsgBox(4096, "Info", "My Drive has been Inserted, Backup My Files!")                 EndIf             ; Now Reset Drive List so more insertions can also be detected accurately                 UpdateDrives()             EndIf     EndSwitch EndFunc  ;==>DeviceChange ; This just jumps through the new Drive List, comparing them until it finds the entry that is in the new one that isn't in the old one Func FindNewDrive()     $Temp = DriveGetDrive( "REMOVABLE" )     For $i = 1 to $Temp[0]         $Old = False         For $j = 1 to $DRIVES[0]             If $DRIVES[$j] == $Temp[$i] Then $Old = True         Next         If $Old == False Then Return $Temp[$i]       Next EndFunc  ;==>FindNewDrive ; Just to keep things neat, and so if Variables Ever Change, this makes updating easier Func UpdateDrives()     $Drives = DriveGetDrive( $Drive_Type ) EndFunc  ;==>UpdateDrives ; Main Loop to Keep the Program Open ; No Real Way of ending this program, except for just killing the process ; Which is what I want, an always on backup for my drive every time I insert it While 1     $GuiMsg = GUIGetMsg() ; This is needed because the watch event above not only triggers before a USB Drive is inserted/removed, ; but also AFTER insertion too, and if not reset, a subsequent CD insertion will trigger it again. ; So, every second, we reset $WATCH, to keep things clean     Sleep (1000)     $WATCH = False WEnd

As good as the above code works, I'd still love to see the WMI version. I'll write it myself, I just need to know how to register a WMI event watcher to watch for events for me. I know how to do that with VB, but I can't seem to find how to do it in Autoit, and I have this feeling it is possible, I just don't know how to do it. Any help from people here who know more about that than I do would be greatly appreciated.

#7 SkinnyWhiteGuy


    Feed the bunny!

  • Active Members
  • PipPipPipPipPipPip
  • 421 posts

Posted 12 March 2007 - 05:23 AM

Ok, I got a little more time to read around, and found an answer to my own question. I discovered the ExecNotificationQuery, and found that it does the trick just as nice as before, maybe even better. The code at least looks simpler, not as jumbled, just a little more above my head now...

I give you the WMI version of the USB Backup Script

Plain Text         
$wbemFlagReturnImmediately = 0x10 $wbemFlagForwardOnly = 0x20 $colItems = "" $strComputer = "localhost" $MyDrive = "SCSD TOOLS" $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2") $m_MediaConnectWatcher = $objWMIService.ExecNotificationQuery("SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_DiskDrive'") While 1     $mbo = $m_MediaConnectWatcher.NextEvent     $obj = $mbo.TargetInstance     If $obj.InterfaceType == "USB" Then         $New = GetDriveLetterFromDisk($obj.Name)         $Label = DriveGetLabel($New)         If $Label == $MyDrive Then             MsgBox(4096, "Info", "My drive has been plugged in, backup my files!")         EndIf     EndIf WEnd Func GetDriveLetterFromDisk($name)     $ans = ""     $name = StringReplace($name,"\","\\")     $oq_part = $objWMIService.ExecQuery("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=""" & $name & """} WHERE AssocClass = Win32_DiskDriveToDiskPartition", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)     If IsObj($oq_part) Then         For $obj_part In $oq_part             $oq_disk = $objWMIService.ExecQuery("ASSOCIATORS OF {Win32_DiskPartition.DeviceID=""" & $obj_part.DeviceID & """} WHERE AssocClass = Win32_LogicalDiskToPartition", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)             If IsObj($oq_disk) Then                 For $obj_disk in $oq_disk                     $ans = $ans & $obj_disk.Name                 Next             EndIf         Next     EndIf         Return $ans EndFunc

I hope someone else can find some use for what I did here. I know I have.

#8 ptrex



  • MVPs
  • 2,431 posts

Posted 12 March 2007 - 10:18 AM


Perfect !! :whistle:

This belongs in the SCRIPT EXAMPLES section !!






  • Active Members
  • 14 posts

Posted 22 August 2014 - 05:28 PM

I sometimes get a Line 10 Error: "Variable must be of type "Object" with the USB Backup Script. Anyone else get this?

#10 careca



  • Active Members
  • PipPipPipPipPipPip
  • 821 posts

Posted 22 August 2014 - 08:00 PM

i'll answer you in another 7 years from now..

You do realize, autoit has changed from then to now, it's possible there are going to be incompatibilities with those old scripts.

BeatsPlayer - My Music player


"Know what really grinds my gears? Those people who quote whole posts for no reason." Peter Griffin

#11 Michael82



  • New Members
  • 1 posts

Posted 02 September 2014 - 04:50 AM

I have been search the net for hours trying to find a way to get this to work. Hopefully some one here can let me know how.


I have a USB game pad (HID) and am trying to write the script to launch a program once inserted and then close that program once removed. When i plug in the HID device it doesn't seem to register the same way a USB drive does. 


Is there anything way that i can do this? I am on a Windows 8.1 box.


Thank ins advance for any help

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users