Sign in to follow this  
Followers 0
gingerbloke

Monitor for a USB drive connection

8 posts in this topic

I am very new to AutoIt and would appreciate any help I can get with the following:

I am writing a small program to backup my system. It works in the following way:

It waits for a specific USB Storage Drive to be connected to my computer.

If it finds this drive is connected then (using someone else's code from this forum) it finds the drive letter assigned to that device.

With this information, I will then be able to backup key information on my system to the USB Drive (plus eventually I hope to 'Image the System as part of the backup but that will probably be a different post)

The problem is that the way it finds the drive letter for connected USB device is very slow and I would like it to be faster if possible. (please ignore the message boxes in the below code, they were for checking the progress of the program running)

This is the code I am using:

DIM $DRIVR

DIM $COUNTER

dim $COUNTERA

DIM $BACKUPDRIVESERIAL

DIM $BACKUPDRIVE

DIM $BACKUPDRIVEENUM

DIM $LEFTBACKUPDRIVEENUM

dim $LENBACKUPDRIVEENUM

dim $REGISTRYDRIVELOCATION

dim $REGISTRYPATH

DIM $DRIVEATTACHED

DIM $FOUNDDRIVESERIAL

DIM $MISCSTRING

DIM $DRIVELETTER

dim $var

dim $i

dim $PROGRAMEND

;**************************************************************************************************

;This is the registry entry of the USB drive to search for

$BACKUPDRIVE = "USBSTOR\Disk&Ven_Maxtor&Prod_Basics_Desktop&Rev_0128\2HBARK6E____&0"

;**************************************************************************************************

;**************************************************************************************************

;THIS IS THE MAIN PROGRAM CALL

Do

SLEEP (5000) ;Wait 5 seconds before re-scanning

CheckRegistryForDevice(); This works out names and locations of relevent registry entries for the device

CheckDriveAttached();Checks if the drive is connected and sub calls other function to find it's drive letter

;If drive attached then notify user we are preparing to backup and find drive letter

if $DRIVEATTACHED = 1 then

MsgBox(0, $DRIVELETTER, $FOUNDDRIVESERIAL)

;Warn User Backup Starting Shortly

;Check if Drive is attached

CheckDriveLetter()

endif

; MsgBox(0, $DRIVELETTER, $FOUNDDRIVESERIAL)

if $DRIVELETTER <> "" then MsgBox(0, $DRIVELETTER,$FOUNDDRIVESERIAL);Run The Backup Program.

until $PROGRAMEND = 5

exit

;**************************************************************************************************

;FUNCTIONS ARE HERE

;**************************************************************************************************

;**************************************************************************************************

Func CheckRegistryForDevice()

;This works out the device serial number that should be held in the registry

;Uses device name ie $BACKUPDRIVE = "USBSTOR\Disk&Ven_Maxtor&Prod_Basics_Desktop&Rev_0128\2HBARK6E____&0"

;And looks for this device where Disk Drives (fixed and Removable are located

$PROGRAMEND = 0

$REGISTRYPATH = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses\{53f56307-b6bf-11d0-94f2-00a0c91efb8b}"; Location where Disk Drive info found

;SET THE USB DEVICE SERIAL NO & REGISTRY TEXTS

$BACKUPDRIVEENUM = StringReplace($BACKUPDRIVE, "\", "#")

$BACKUPDRIVEENUM = "##?#" & $BACKUPDRIVEENUM

$LENBACKUPDRIVEENUM = StringLen($BACKUPDRIVEENUM)

;**************************************************************************************************

;Work Out the Serial Number for this device

$LENBACKUPDRIVEENUM = StringLen($BACKUPDRIVE)

for $COUNTER = 1 to $LENBACKUPDRIVEENUM

$MISCSTRING = StringMid($BACKUPDRIVE, $COUNTER, 1)

if $MISCSTRING = "\" then ;Strip Off the left Hand Side of the string

$COUNTERA = $LENBACKUPDRIVEENUM - $COUNTER

$BACKUPDRIVESERIAL = StringRight($BACKUPDRIVE, $COUNTERA)

; MsgBox(0, $BACKUPDRIVESERIAL, $COUNTERA)

endif

next

;Now strip off the unnecessary right side of the String

$LENBACKUPDRIVEENUM = StringLen($BACKUPDRIVESERIAL)

for $COUNTER = 1 to $LENBACKUPDRIVEENUM

$MISCSTRING = StringMid($BACKUPDRIVESERIAL, $COUNTER, 1)

;MsgBox(0, $MISCSTRING, $COUNTER)

if $MISCSTRING = "_" then ;Strip Off the right Hand Side of the string

$COUNTERA = $COUNTER - 1

$BACKUPDRIVESERIAL = StringLeft($BACKUPDRIVESERIAL, $COUNTERA)

$BACKUPDRIVESERIAL =StringStripWS($BACKUPDRIVESERIAL, 2)

; MsgBox(0, $BACKUPDRIVESERIAL, $COUNTERA)

;Got $BACKUPDRIVESERIAL

exitloop

endif

next

EndFunc

Func CheckDriveAttached()

;--------------------------------------------------------------------------------------------------

;Get All Installed Drives on The System and check for our device and if it is connected

$i = 0

$DRIVEATTACHED = 0

while $REGISTRYDRIVELOCATION <> "end"

$i= $i + 1

$REGISTRYDRIVELOCATION = ""

$REGISTRYDRIVELOCATION = RegEnumKey($REGISTRYPATH, $i)

If @error <> 0 then ExitLoop

;Check for our device entry here

$LEFTBACKUPDRIVEENUM = StringLeft($REGISTRYDRIVELOCATION, $LENBACKUPDRIVEENUM)

;Now check to see if we can find the registry location of our device

if $LEFTBACKUPDRIVEENUM = $BACKUPDRIVEENUM then

;Now check if the device is connected at the moment

$REGISTRYDRIVELOCATION = $REGISTRYPATH & "\" & $REGISTRYDRIVELOCATION & "\Control"

$DRIVEATTACHED = RegRead($REGISTRYDRIVELOCATION, "ReferenceCount")

; if $DRIVEATTACHED = 1 then CheckDriveLetter();MsgBox(4096, "Drive attached", $REGISTRYDRIVELOCATION) ;Device connected so prepare to begin backup

endif

wend

;--------------------------------------------------------------------------------------------------

endfunc

Func CheckDriveLetter()

;Now Get the drive letter for our device by checking each connected drive letter in turn

$varall = DriveGetDrive("all")

for $i = 1 to $varall[0]

$FOUNDDRIVESERIAL = ""

$DRIVR = $varall[$i]

getSerialNumberFromDriveLetter(); For the given Drive letter find the devices serial number to see if it is our device

MsgBox(0, $FOUNDDRIVESERIAL, $DRIVR)

if $FOUNDDRIVESERIAL = $BACKUPDRIVESERIAL then

$DRIVELETTER = $DRIVR

MsgBox(0, $DRIVELETTER, $FOUNDDRIVESERIAL)

exitloop

endif

Next

endfunc

Func getSerialNumberFromDriveLetter()

;**************************************************************************

;************* THIS PART IS THE BOTTLENECK IN THE PROGRAM *****************

;**************************************************************************

;Search each provided drive letter for it's serial number $DRIVR

Dim $I = 0 , $X = 0 ,$ComputerName = '.'

$wmiServices = ObjGet ("winmgmts:{impersonationLevel=Impersonate}!//" & $ComputerName)

$wmiDiskDrives = $wmiServices.InstancesOf("Win32_DiskDrive")

For $wmiDiskDrive In $wmiDiskDrives

$I = $I + 1

$query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" & $wmiDiskDrive.DeviceID & "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition"

$wmiDiskPartitions = $wmiServices.ExecQuery($query)

For $wmiDiskPartition In $wmiDiskPartitions

$wmiLogicalDisks = $wmiServices.ExecQuery ("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" & $wmiDiskPartition.DeviceID & "'} WHERE AssocClass = Win32_LogicalDiskToPartition")

For $wmiLogicalDisk In $wmiLogicalDisks

IF StringUpper($wmiLogicalDisk.DeviceID) = StringUpper($DRIVR) Then $X = $I

Next

Next

Next

$I = 0

$PhysicalMedia = $wmiServices.InstancesOf("Win32_PhysicalMedia")

For $Item In $PhysicalMedia

$I = $I + 1

IF $I = $X Then

$FOUNDDRIVESERIAL = $Item.SerialNumber

$FOUNDDRIVESERIAL =StringStripWS($FOUNDDRIVESERIAL, 2)

;$DRIVELETTER = $DRIVR

endif

Next

EndFunc

Thanks for your time ...

Share this post


Link to post
Share on other sites



gingerbloke,

Welcome to the AutoIt forums. :)

A good start - some code to work on and a clear question. I wish some other newcomers would do the same.

Here is the code I use to get USB serials (credit to spudw2k):

; credit spudw2k

$aDrives = DriveGetDrive("Removable")

For $i = 1 To $aDrives[0]
    $id = _GetPNPDeviceID($aDrives[$i])
    MsgBox(0, $aDrives[$i], $id)
Next

Func _GetPNPDeviceID($drive, $fullid = 0)
    $objWMIService = ObjGet("winmgmts:{impersonationLevel=Impersonate}!\\.\root\cimv2")
    If Not IsObj($objWMIService) Then Return -1 ;Failed to Connect to WMI on Local Machine

    $colDevice = $objWMIService.ExecQuery("SELECT * from Win32_LogicalDiskToPartition")
    $var = ""
    For $objItem In $colDevice
        If StringInStr($objItem.Dependent, $drive) Then
            $var = StringTrimLeft($objItem.Antecedent, StringInStr($objItem.Antecedent, "="))
        EndIf
    Next
    If Not $var Then Return -2 ;Failed to Find Drive Letter

    $colDevice = $objWMIService.ExecQuery("SELECT * from Win32_DiskDriveToDiskPartition")
    $diskpartition = $var
    $var = ""
    For $objItem In $colDevice
        If StringInStr($objItem.Dependent, $diskpartition) Then
            $var = StringTrimLeft($objItem.Antecedent, StringInStr($objItem.Antecedent, "="))
        EndIf
    Next
    If Not $var Then Return -3 ;Failed to Find Physical Drive #

    $colDevice = $objWMIService.ExecQuery("SELECT * from Win32_DiskDrive")
    $physicaldrive = StringReplace(StringReplace($var, "\\", "\"), '"', "")
    $var = ""
    For $objItem In $colDevice
        If $objItem.DeviceID = $physicaldrive Then
            $var = $objItem.PNPDeviceID
        EndIf
    Next
    If Not $var Then Return -4 ;Failed to Find PNPDeviceID

    If Not $fullid Then $var = StringTrimLeft($var, StringInStr($var, "\", 0, -1)) ;Return Ugly Full PNPDeviceID
    Return $var
EndFunc   ;==>_GetPNPDeviceID

It is pretty fast on my machine - I hope it is fast enough for you! B)

M23

P.S. Please use Code tags when you post. Put [autoit ] before and [/autoit ] after your code (but omit the trailing space - it is only there so the tags display here). ;)


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Thanks for your speedy reply M23, much appreciated. ;)

I have run your script but for some reason it returns -2 for all drives found.

I will have a play around and see if I can get it to work for me. It may be because I am working on VISTA so I will also try it by booting into my XP and Win7. B)

Also, thanks for the [autoit ] and [/autoit ] pointer, I wondered how to do that with the code. :)

Gingerbloke (but to you Ginge)

Share this post


Link to post
Share on other sites

Ginge,

I too am running Vista and I get -2 from "removable" drives such as my card readers, but a valid ID (and an additional drive in the array) as soon as I put a thumb drive into a USB slot.

Try looking at the array to see what drives the script finds:

#include <Array.au3>

$aDrives = DriveGetDrive("Removable")

_ArrayDisplay($aDrives)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

M23

Sorted! :) on my system the attached USB Hard Drive is detected as a "Local Disk" Type so the Drive letter does not appear in the list. Ive changed it to fixed and it finds the device and serial number really quick.

This has also helped me find out which Partitions are part of the same physical device (another project I am working on) because the different drive letter's gives the same serial number for that device.

Thanks for your help M23, I owe you one

Ginge

Share this post


Link to post
Share on other sites

Funnily enough I am working on a artifact project in College and have been programming a USB Storage program that supports;

[*] Different USB Drives (Identifies different drives using DriveGetSerial and backs up accordingly)

[*] Full Backup

[*] Incremental Backup

[*] Backups you're data when working from you're USB Device as you're working (for example, you're working on a file called, 'Test.txt' which is located on your USB drive,

- every time you save that document it will backup that file to the directory you specified earlier (in the configuration menu).

If you want the source code then I'll PM you it, I'm not going to release it until my project has finished but it may help with the project you're currently under-taking.

AwAke.

Share this post


Link to post
Share on other sites

Hello,

It's possible to have a copy of your source code please ?

I need a script for front end user who need to backup profile on a USB drive (Full or Incremental)

Thanks

Share this post


Link to post
Share on other sites

Neo2102,

As AwAke has not been active here since Mar 2010 I doubt he will answer. ;)

In future, please do not necro-post in threads like this when there is little chance of a response. :)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0