Sign in to follow this  
Followers 0
psikoh

USB Mass Storage Device detect

13 posts in this topic

#1 ·  Posted (edited)

I am trying to write a backup script that will log onto a network machine, grab the drive letters, and then back them up sequentially. That part works fine. The part I'm having problems is that when it grabs the drive letters it also grabs any USB Mass Storage devices attached. These aren't USB keys or anything, they are actual usb hard drives.

I've tried a few scripts from on here but they all see the usb devices as fixed disks.

Is there a way I can exclude these from the list?

CODE
Func _ComputerGetDrives(ByRef $aDriveInfo, $sDriveType = "FIXED")

Local $drive

$drive = DriveGetDrive($sDriveType)

If NOT @error Then

Dim $aDriveInfo[uBound($drive)][6]

$aDriveInfo[0][0] = $drive[0]

For $i = 1 To $aDriveInfo[0][0] Step 1

$aDriveInfo[$i][0] = StringUpper($drive[$i])

$aDriveInfo[$i][1] = DriveGetFileSystem($drive[$i])

If @error Then SetError(1, 2, 0)

$aDriveInfo[$i][2] = DriveGetLabel($drive[$i])

If @error Then SetError(1, 3, 0)

$aDriveInfo[$i][3] = DriveGetSerial($drive[$i])

If @error Then SetError(1, 4, 0)

$aDriveInfo[$i][4] = DriveSpaceFree($drive[$i])

If @error Then SetError(1, 5, 0)

$aDriveInfo[$i][5] = DriveSpaceTotal($drive[$i])

If @error Then SetError(1, 6, 0)

Next

Else

SetError(1, 1, 0)

EndIf

EndFunc ;_ComputerGetDrives

Dim $Drives

_ComputerGetDrives($Drives) ;Defaults to "FIXED"

Local $backup = ("c:\backup.ini")

FileOpen($backup,1)

FileWrite($backup, '[Drives]' & @CRLF)

For $i = 1 To $Drives[0][0] Step 1

FileWrite($backup, 'Drive=' & $Drives[$i][0] & @CRLF)

Next

$Drives = "All"

_ComputerGetDrives($Drives) ;Defaults to "FIXED"

Local $backup = ("c:\backup.ini")

FileOpen($backup,1)

FileWrite($backup, '[Drives]' & @CRLF)

For $i = 1 To $Drives[0][0] Step 1

FileWrite($backup, 'Drive=' & $Drives[$i][0] & @CRLF)

Next

Note: This is from the CompInfo UDFs as it works well for what it does :whistle:

Edited by psikoh

Share this post


Link to post
Share on other sites



If you try "REMOVABLE" do you get any usb drives?


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

If you try "REMOVABLE" do you get any usb drives?

No, I tried removable and no drives came up until i plugged in a usb stick.

I think I may have found a way around it by disabling all usb devices using devcon before i check for drive letters, then enabling them again after. It's messy though and I'd prefer to do it without disabling them.

Share this post


Link to post
Share on other sites

I looked at that script, but that won't detect a USB drive that was plugged in before the script starts. The drives I'm trying to ignore are always plugged in, and only removed once in a blue moon.

It also doesn't detect the hard disks being plugged in / unplugged. It detects USB sticks no problem though.

Share this post


Link to post
Share on other sites

These are like external hard drives, right? I've got one, and I've also noticed that Windows recognizes it as a fixed disk. If I had to guess, I'd say there's no real way to tell the difference, what you suggested with disabling USB devices sounds like a decent idea, just make sure nothing is writing to those drives before you disable them (not sure how you'd check that...).

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

The script below return an array with all hard disk letter excluding USB drive.

#include <Array.au3>

$ret = _GetHardDiskLetter()
_ArrayDisplay($ret, 'Hard Disk List')

Func _GetHardDiskLetter()
    Local $wbemFlagReturnImmediately = 0x10
    Local $wbemFlagForwardOnly = 0x20
    Local $sName
    Local $colItems = ""
    Local $strComputer = "localhost"
    Dim $sDrive[1]

    $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_DiskDrive", "WQL", _
                                          $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
    If IsObj($colItems) then
        For $objItem In $colItems
            If $objItem.InterfaceType <> 'usb' Then
                $sName = StringReplace($objItem.DeviceID, '\', '\\')
                $objPartition = $objWMIService.ExecQuery("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=""" & $sName & """} WHERE AssocClass = Win32_DiskDriveToDiskPartition", "WQL", _
                                          $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
                If IsObj($objPartition) Then
                    For $objPart In $objPartition
                        $objLogicalDisk = $objWMIService.ExecQuery("ASSOCIATORS OF {Win32_DiskPartition.DeviceID=""" & $objPart.DeviceID & _
                                          """} WHERE AssocClass = Win32_LogicalDiskToPartition", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
                        If IsObj($objLogicalDisk) Then
                            For $objDisk in $objLogicalDisk
                                ReDim $sDrive[UBound($sDrive) + 1]
                                $sDrive[UBound($sDrive) - 1] = $objDisk.Name
                            Next
                        EndIf   
                    Next                                    
                EndIf
            EndIf
        Next
        $sDrive[0] = UBound($sDrive) - 1
        If $sDrive[0] = 0 Then $sDrive = ''
    Else
        Msgbox(0,"WMI Output","No WMI Objects Found for class: " & "Win32_DiskDrive" )
    Endif
    Return($sDrive)
EndFunc
Edited by Danny35d

AutoIt Scripts:NetPrinter - Network Printer UtilityRobocopyGUI - GUI interface for M$ robocopy command line

Share this post


Link to post
Share on other sites

I tried this code and did not get any drives back. Any ideas what I might be doing wrong? Drives C: D: E: T: are on internal drives (NTFS format) and U: is a USB HDD.

The script below return an array with all hard disk letter excluding USB drive.

#include <Array.au3>

$ret = _GetHardDiskLetter()
_ArrayDisplay($ret, 'Hard Disk List')

Func _GetHardDiskLetter()
    Local $wbemFlagReturnImmediately = 0x10
    Local $wbemFlagForwardOnly = 0x20
    Local $sName
    Local $colItems = ""
    Local $strComputer = "localhost"
    Dim $sDrive[1]

    $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_DiskDrive", "WQL", _
                                          $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
    If IsObj($colItems) then
        For $objItem In $colItems
            If $objItem.InterfaceType <> 'usb' Then
                $sName = StringReplace($objItem.DeviceID, '\', '\\')
                $objPartition = $objWMIService.ExecQuery("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=""" & $sName & """} WHERE AssocClass = Win32_DiskDriveToDiskPartition", "WQL", _
                                          $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
                If IsObj($objPartition) Then
                    For $objPart In $objPartition
                        $objLogicalDisk = $objWMIService.ExecQuery("ASSOCIATORS OF {Win32_DiskPartition.DeviceID=""" & $objPart.DeviceID & _
                                          """} WHERE AssocClass = Win32_LogicalDiskToPartition", "WQL", $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
                        If IsObj($objLogicalDisk) Then
                            For $objDisk in $objLogicalDisk
                                ReDim $sDrive[UBound($sDrive) + 1]
                                $sDrive[UBound($sDrive) - 1] = $objDisk.Name
                            Next
                        EndIf   
                    Next                                    
                EndIf
            EndIf
        Next
        $sDrive[0] = UBound($sDrive) - 1
        If $sDrive[0] = 0 Then $sDrive = ''
    Else
        Msgbox(0,"WMI Output","No WMI Objects Found for class: " & "Win32_DiskDrive" )
    Endif
    Return($sDrive)
EndFunc

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

I tried this code and did not get any drives back. Any ideas what I might be doing wrong? Drives C: D: E: T: are on internal drives (NTFS format) and U: is a USB HDD.

This might be too primitive, but how about putting a magic file on each of the USBHDDs? Something like <DRIVELETTER>:\MAGIC_BACKUP.NO - then your script checks if file exists and if so excludes the drive...

Edited by longtex

Nobody needs a job. Not much, anyway. Before you need a job, there's a lot of other stuff you need. More or less in order of how badly you need them: AIR, WATER, FOOD, SHELTER, CLOTHING, COMPANIONSHIP, and ACTIVITY. You've been led to believe you need money to "pay" someone else to provide those for you - all but AIR, so far. How long is it going to be before you have to "pay" for AIR, too?

Share this post


Link to post
Share on other sites

Unfortunately I can't do that. This is part of a remote program that is pushed out to various computers that may or may not have USB HDDs and the owners have full control over them if they exist so the file could just as easily be deleted.

Share this post


Link to post
Share on other sites

Is this any use?

#include <array.au3>

$drives = _GetNoneUSBDrives()
_ArrayDisplay($drives)

Func _GetNoneUSBDrives()
    Local $aDletters[1]
     
    $strComputer = "."
    Local $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2")

    Local $colDiskDrives = $objWMIService.ExecQuery("SELECT * FROM Win32_DiskDrive")
     
    For $objDrive In $colDiskDrives
        If $objDrive.InterfaceType = 'usb' then Continueloop
       ConsoleWrite( "Physical Disk: " & $objDrive.Caption & " -- " & $objDrive.DeviceID & " -- Interface type: " & $objDrive.InterfaceType &  @crlf)
        $strDeviceID = StringReplace($objDrive.DeviceID, "\", "\\")
        Local $colPartitions = $objWMIService.ExecQuery _
            ("ASSOCIATORS OF {Win32_DiskDrive.DeviceID=""" & _
                $strDeviceID & """} WHERE AssocClass = " & _
                    "Win32_DiskDriveToDiskPartition")
     
        For $objPartition In $colPartitions
            ConsoleWrite( "Disk Partition: " & $objPartition.DeviceID & @crlf)
            Local $colLogicalDisks = $objWMIService.ExecQuery _
                ("ASSOCIATORS OF {Win32_DiskPartition.DeviceID=""" & _
                    $objPartition.DeviceID & """} WHERE AssocClass = " & _
                        "Win32_LogicalDiskToPartition")
     
            For $objLogicalDisk In $colLogicalDisks
                ConsoleWrite( "Logical Disk: " & $objLogicalDisk.DeviceID & @crlf)
                _ArrayAdd($aDletters,$objLogicalDisk.DeviceID )
            Next
        ;ConsoleWrite("...." & @Crlf)
        Next
      ;ConsoleWrite("______" & @Crlf)
    Next

    Return $aDletters

EndFunc

Share this post


Link to post
Share on other sites

The script below return an array with all hard disk letter excluding USB drive.

Ooh... new toys! ;)

Thanks for that. I'm starting a rewrite into a more general UDF. So far all it does is list DeviceID and Interface, but more is coming. The intent is to be able to pass and interface and it will return an array of drives on that interface (kind of the opposite of the topic, but more generally useful):

#include <Array.au3>

$avRET = _GetHardDiskInterface()
_ArrayDisplay($avRET, 'Hard Disk Interfaces')

Func _GetHardDiskInterface($sIntfc = "")
    Local $wbemFlagReturnImmediately = 0x10
    Local $wbemFlagForwardOnly = 0x20
    Local $wbemFlags = $wbemFlagReturnImmediately + $wbemFlagForwardOnly
    Local $sComputer = @ComputerName
    Local $avDrives[1] = [0]

    Local $oWMI = ObjGet("winmgmts:\\" & $sComputer & "\root\CIMV2")
    Local $colDrives = $oWMI.ExecQuery ("SELECT * FROM Win32_DiskDrive", "WQL", $wbemFlags)
    If IsObj($colDrives) Then
        For $oDrive In $colDrives
            _ArrayAdd($avDrives, $oDrive.DeviceID & " = " & $oDrive.InterfaceType)
        Next
        $avDrives[0] = UBound($avDrives) - 1
    Else
        MsgBox(16, "Error", "No WMI Objects Found for class: Win32_DiskDrive")
    EndIf
    Return ($avDrives)
EndFunc   ;==>_GetHardDiskInterface

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

EDIT: I wish to thank everybody, especially ChrisL, for the work developing this wonderful code! Thanks very much!

Here is my modified version of ChrisL's code:

Func _DrivesFromBusType( $Bus = "" )
    Local $aDletters = "", $strComputer = "."
    Local $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2")
    Local $colDiskDrives = $objWMIService.ExecQuery("SELECT * FROM Win32_DiskDrive")
     
    For $objDrive In $colDiskDrives
        If $Bus <> "" and $objDrive.InterfaceType <> $Bus then Continueloop
        ConsoleWrite( "Physical Disk: " & $objDrive.Caption & " -- " & $objDrive.DeviceID & " (" & $objDrive.InterfaceType & ")" &  @crlf)
        $strDeviceID = StringReplace($objDrive.DeviceID, "\", "\\")
        ConsoleWrite( $objDrive.DeviceID & " = " & $objDrive.PNPDeviceID & @CRLF )
        Local $colPartitions = $objWMIService.ExecQuery( "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=""" & _
                $strDeviceID & """} WHERE AssocClass = Win32_DiskDriveToDiskPartition" )
        For $objPartition In $colPartitions
            ConsoleWrite( "Disk Partition: " & $objPartition.DeviceID & @crlf)
            Local $colLogicalDisks = $objWMIService.ExecQuery( "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=""" & _
                    $objPartition.DeviceID & """} WHERE AssocClass = Win32_LogicalDisk " & $Floppy )
            For $objLogicalDisk In $colLogicalDisks
                ConsoleWrite( "Logical Disk: " & $objLogicalDisk.DeviceID & @crlf)
                $aDletters = $aDletters & $objLogicalDisk.DeviceID & "|"
            Next
        Next
    Next
    Return $aDletters
EndFunc
The _DrivesFromBusType takes one parameter and returns a string of drives delimited by "|". Valid parameters seem to be "IDE", "USB", and "1394" (FireWire). Passing no parameter to the function gets all fixed drive letters attached to the system.

However, here is my problem. First, here is the console output from the above code:

Physical Disk: Generic USB CF Reader USB Device -- \\.\PHYSICALDRIVE3 (USB)
\\.\PHYSICALDRIVE3 = USBSTOR\DISK&VEN_GENERIC&PROD_USB_CF_READER&REV_1.01\9205291&1
Physical Disk: Generic USB MS Reader USB Device -- \\.\PHYSICALDRIVE5 (USB)
\\.\PHYSICALDRIVE5 = USBSTOR\DISK&VEN_GENERIC&PROD_USB_MS_READER&REV_1.03\9205291&3
Physical Disk: Generic USB SD Reader USB Device -- \\.\PHYSICALDRIVE2 (USB)
\\.\PHYSICALDRIVE2 = USBSTOR\DISK&VEN_GENERIC&PROD_USB_SD_READER&REV_1.00\9205291&0
Physical Disk: Generic USB SM Reader USB Device -- \\.\PHYSICALDRIVE4 (USB)
\\.\PHYSICALDRIVE4 = USBSTOR\DISK&VEN_GENERIC&PROD_USB_SM_READER&REV_1.02\9205291&2

Now, I've also got a piece of code that returns information from the HKLM\SYSTEM\MountedDevices key. Here it is:

$usbdev = RegRead( "HKLM\SYSTEM\MountedDevices", "\DosDevices\" & $Drv )
$usbdev = _HexToString( StringReplace( $usbdev, "00", "" ) )
ConsoleWrite( "Drive " & $Drv & " = " & $UsbDev & @CRLF )
Where $Drv is the drive letter being questioned.

The output of the above code for the USB is this:

Drive u: = \??\STORAGE#RemovableMedia#7&37786a0b&0&RM#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}
Drive v: = \??\STORAGE#RemovableMedia#7&23415857&0&RM#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}
Drive w: = \??\STORAGE#RemovableMedia#7&168e5ac5&0&RM#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}
Drive x: = \??\STORAGE#RemovableMedia#7&7ad55db&0&RM#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}

How do I associate a drive letter with a USB device description passed back by WMI? I know each of the above drives are one of the slots on my card reader. Any assistance would be greatly appreciated!

Edited by Dougiefresh

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