Jump to content

Authorized usb stick detected, but drive letter needed


Recommended Posts

Hello guys!

I am a german programmer and I need to detect if a specific USB stick is connected with the computer. If this USB stick is connected another actions can follow. First action of the user should be: Connecting the USB stick to the computer. Second action: Start the AutoItScript and following the script instructions.

My problem is not to detect the authorized USB stick. The problem is to find out which drive letter have this USB stick on the computer (e.g. F:, H:, I:).

I have used the function Func GetDriveLetterFromDisk($name) which I have found several times here in the topics. But I don't find the solution for my problem.

Who can help me or give the completed code back for detecting the drive letter? Thank you very much in advance!!!!

CODE
$onlyThisStickIsPreferred = "USB\VID_0781&PID_540E\000016A0787491CB"

$USBmassStorgageName1="USB-Massenspeicher"

$USBmassStorgageName2="USB-Massenspeichergerät"

$strComputer = "."

$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")

$colItems = $objWMIService.ExecQuery("Select * From Win32_USBControllerDevice")

If IsObj($colItems) then

LogIt("++++++++++++++++++++++++")

LogIt("!! USB objects exists !!")

LogIt("++++++++++++++++++++++++")

For $objDevice In $colItems

$strDeviceName = $objDevice.Dependent

$strQuotes = Chr(34)

$strDeviceName = StringReplace($strDeviceName, $strQuotes, "")

$arrDeviceNames = StringSplit($strDeviceName, "=")

$strDeviceName = $arrDeviceNames[2]

LogIt("======================================")

LogIt("$arrDeviceNames[1]=" & $arrDeviceNames[1])

LogIt("$arrDeviceNames[2]=" & $arrDeviceNames[2])

$Drive0 = GetDriveLetterFromDisk($arrDeviceNames[2])

LogIt("Drive0 =" & $Drive0)

$colUSBDevices = $objWMIService.ExecQuery("Select * From Win32_PnPEntity Where DeviceID = '" & $strDeviceName & "'")

For $objUSBDevice in $colUSBDevices

$Description = $objUSBDevice.Description

$DeviceID = $objUSBDevice.DeviceID

$DeviceName = $objUSBDevice.Name

$PnPDeviceID = $objUSBDevice.PnPDeviceID

LogIt("--------------------------------------")

LogIt("Description: " & $Description)

LogIt("DeviceId : " & $DeviceID)

LogIt("DeviceName : " & $DeviceName)

LogIt("PnPDeviceID: " & $PnPDeviceID)

if ($Description = $USBmassStorgageName1) Or ($Description = $USBmassStorgageName2) Then

if $DeviceID = $onlyThisStickIsPreferred Then

LogIt("***** Authorized stick is used *****")

; Now I need the drive letter of this drive, but this is not functional

$Drive = GetDriveLetterFromDisk($DeviceName)

LogIt("Drive : " & $Drive) ; I get everytime a empty string

EndIf

EndIf

NEXT

LogIt(" ")

Next

Else

LogIt("+++++++++++++++++++++++")

LogIt("No USB Objects existing")

LogIt("+++++++++++++++++++++++")

Endif

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

Func LogIt($sText)

IF @Compiled THEN

DllCall("kernel32.dll", "none", "OutputDebugString", "str", $sText)

Else

ConsoleWrite($sText & @LF)

EndIf

EndFunc

Func GetDriveLetterFromDisk($name)

Local $wbemFlagReturnImmediately = 0x10

Local $wbemFlagForwardOnly = 0x20

Local $strComputers = ".", $objEvent = 0

Local $objWMIServices = ObjGet("winmgmts:\\" & $strComputers & "\root\cimv2")

$ans = ""

$name = StringReplace($name,"\","\\")

$oq_part = $objWMIServices.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 = $objWMIServices.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

USB mass storages in germany have following descriptions "USB-Massenspeicher" (Windows2000) or "USB-Massenspeichergerät" (WindowsXP)

horrscht

Link to comment
Share on other sites

Hi,

es gibt auch www.autoit.de muttley

Du kannst ja einfach durch alle LW iterieren und den DriveGetLabel prüfen oder auf eine bestimtme Datei auf dem Stick prüfen If FileExistes A:\bla.txt und wenn ja dann ... usw.

Gibt da viele Möglichkeiten. Wenn du die Serial kennst, kannst du auch diese verwenden

Mega

Scripts & functions Organize Includes Let Scite organize the include files

Yahtzee The game "Yahtzee" (Kniffel, DiceLion)

LoginWrapper Secure scripts by adding a query (authentication)

_RunOnlyOnThis UDF Make sure that a script can only be executed on ... (Windows / HD / ...)

Internet-Café Server/Client Application Open CD, Start Browser, Lock remote client, etc.

MultipleFuncsWithOneHotkey Start different funcs by hitting one hotkey different times

Link to comment
Share on other sites

Hi Mega!

Der VolumeName kann zu leicht abgeändert werden, wenn ich den VolumeName suche. Eine zu suchende Datei hat auch den Nachteil, dass sie evtl. auch mal gelöscht sein könnte => ich finde den Stick dann nicht mehr.

Die eindeutige USB-ID versetzt mich in die Lage den User-Fehler von Verwaltungsangestellten in Grenzen zu halten. Mir fehlt jetzt nur noch die gezielte Ermittlung des Laufwerksbuchstaben vom eindeutig gefundenen Stick.

Es ist in der Vergangenheit schon passiert, dass der USB-Stick aus irgendeinem Grund, dann mal nicht mehr der Laufwerksbuchstabe H: war, wie ich im restlichen (nicht veröffentlichten) Skript voraussetzte, sondern der Buchstabe I:, dann schlug der Rest fehl und ich bekam Anrufe von der Verwaltungsangestellten.

Dennoch danke für Deinen Hinweis, mit der deutschen Webseite.

Gruß, horrscht

Link to comment
Share on other sites

Hi,

was wäre denn für eindeutig an einem USB Stick? Selbst die ID ist nicht eindeutig bei Billiggerstellen.

Mega

Scripts & functions Organize Includes Let Scite organize the include files

Yahtzee The game "Yahtzee" (Kniffel, DiceLion)

LoginWrapper Secure scripts by adding a query (authentication)

_RunOnlyOnThis UDF Make sure that a script can only be executed on ... (Windows / HD / ...)

Internet-Café Server/Client Application Open CD, Start Browser, Lock remote client, etc.

MultipleFuncsWithOneHotkey Start different funcs by hitting one hotkey different times

Link to comment
Share on other sites

Hi Mega!

Es sind vier bauartgleiche Sticks vom gleichen Hersteller, mit alle der gleichen Größe, alle zum selben Zeitpunkt gekauft. Alle 4 Sticks haben eine jeweils eindeutige DeviceID mit der ich sie gemäß meines Skripts unterscheiden kann.

Also es geht - sorry, wenn's blöd klingt - um die Beantwortung meiner Frage, weil unterscheiden kann ich die Sticks mit einem Skript. Ich gebe zu, dass diese Unterscheidung anhand der DeviceID bei manchem Stick fehlschlagen könnte, aber solche Sticks sind in der Firma nicht im Einsatz. Ich möchte schlicht nicht mehr Annrufe haben, dass das Skript fehlschlägt, nur weil - aus welchem Grund auch immer - der Laufwerksbuchstabe nicht wie vorgesehen zugewiesen wird.

Gruß, horrscht

Link to comment
Share on other sites

Hey, I have no clue what either of you have said, so here's the solution I found to do something similar.

Global Const $DBT_DEVICEARRIVAL     = 0x00008000
Global Const $WM_DEVICECHANGE       = 0x0219
Global Const $tagDEV_BROADCAST_HDR  = "dword dbchsize;dword dbchdevicetype;dword dbchreserved"
Global Const $DBT_DEVTYP_VOLUME     = 0x00000002
Global Const $tagDEV_BROADCAST_VOLUME   = "dword dbcvsize;dword dbcvdevicetype;dword dbcvreserved;dword dbcvunitmask;short dbcvflags"
Global Const $DBTF_MEDIA            = 0x0001
Global Const $DBTF_NET              = 0x0002
;Setup The GUI to watch for the DeviceChange Event

GUICreate("Test")
GUIRegisterMsg($WM_DEVICECHANGE, "DeviceChange")

While 1
    Sleep (1000)
WEnd

Func DeviceChange($hWndGUI, $MsgID, $WParam, $LParam)
    $iEvent = $WParam
    If $iEvent = $DBT_DEVICEARRIVAL Then
            $temp = DllStructCreate($tagDEV_BROADCAST_HDR, $LParam)
            $iDeviceType = DllStructGetData($temp, "dbchdevicetype")
            If $iDeviceType = $DBT_DEVTYP_VOLUME Then
                $struct = DllStructCreate($tagDEV_BROADCAST_VOLUME, $LParam)
                $iUnitMask = DllStructGetData($struct, "dbcvunitmask")
                $iFlags = DllStructGetData($struct, "dbcvflags")
                If Not BitAND($iFlags, $DBTF_MEDIA) And Not BitAND($iFlags, $DBTF_NET) Then
                    $sDrive = FirstDriveFromMask($iUnitMask)
                    ConsoleWrite($sDrive & ": was inserted!" & @CRLF)
                EndIf
            EndIf
    EndIf
EndFunc   ;==>DeviceChange

Func FirstDriveFromMask($unitmask)
    Local $i
    For $i = 0 To 25
        If BitAND($unitmask, 0x1) Then ExitLoop
        $unitmask = BitShift($unitmask, 1)
    Next
    Return Chr($i + Asc('A'))
EndFunc

Just as a warning, this will also trigger when a CD-Rom Device is installed, not when a CD is inserted, but when a CD drive is added to a machine (like a USB external drive, or the fake one some USB sticks use). You can easily add a check for that with DriveGetType(), if that's an issue for you.

Edited by SkinnyWhiteGuy
Link to comment
Share on other sites

Global $serial = 821811646

If _getDriveBySerial($serial) Then
    MsgBox(64, 'USB', 'Laufwerk --> ' & _getDriveBySerial($serial), 5)
Else
    MsgBox(16, 'USB', 'Serial nicht gefunden', 5)
EndIf

Func _getDriveBySerial($serial)
    For $i = 65 To 90
        If $serial = DriveGetSerial(Chr($i) & ':') Then Return Chr($i) & ':' 
    Next
    Return 0
EndFunc   ;==>_getDriveBySerial

Scripts & functions Organize Includes Let Scite organize the include files

Yahtzee The game "Yahtzee" (Kniffel, DiceLion)

LoginWrapper Secure scripts by adding a query (authentication)

_RunOnlyOnThis UDF Make sure that a script can only be executed on ... (Windows / HD / ...)

Internet-Café Server/Client Application Open CD, Start Browser, Lock remote client, etc.

MultipleFuncsWithOneHotkey Start different funcs by hitting one hotkey different times

Link to comment
Share on other sites

Hey, I have no clue what either of you have said, so here's the solution I found to do something similar.

Hey!

Thank you for suggestion, but your script detects a added drive while the scripts already runs. But I need to detect the drive and search the drive letter when first the stick is connected to the computer and afterwards the script is started. The reason is the employee starts the script more than one time while the USB stick is connected to the computer.

My information of the detected USB stick is the following:

Description: USB-Massenspeichergerät

DeviceId: USB\VID_090C&PID_1000\20071101114010000382

Exists a possibility to detect the drive letter of my obtained information of the USB disk??

Greetings, horrscht

Link to comment
Share on other sites

Hi Mega!

I write here in english due to the other forum users.

Your suggestion is okay but can I detect or get the serial with my AutoIt-Script with a little change to my script shown above?

$DeviceID = $objUSBDevice.DeviceID => This $DeviceID isn't the serial number, i think so?

My value e.g. of an home office USB stick is:

$DeviceID = "USB\VID_090C&PID_1000\20071101114010000382"

Greetings, horrscht

Link to comment
Share on other sites

As I said before, you need one thing to identify the usb stick. One thing would be the serialID.

I have to search how to get this "USB\VID_090C&PID_1000\20071101114010000382"

so, maybe it is easier to include the 4 serialIds which Autoit detects by DriveGetSerial.

Mega

Scripts & functions Organize Includes Let Scite organize the include files

Yahtzee The game "Yahtzee" (Kniffel, DiceLion)

LoginWrapper Secure scripts by adding a query (authentication)

_RunOnlyOnThis UDF Make sure that a script can only be executed on ... (Windows / HD / ...)

Internet-Café Server/Client Application Open CD, Start Browser, Lock remote client, etc.

MultipleFuncsWithOneHotkey Start different funcs by hitting one hotkey different times

Link to comment
Share on other sites

The reason is the employee starts the script more than one time while the USB stick is connected to the computer.

Look up _Singleton() in the help file, this will allow only 1 running copy of the script

Link to comment
Share on other sites

Hallo Horrscht muttley

Wenn's Dir um den Laufwerksbuchstaben geht wirf mal einen Blick auf das hier:

http://www.uwe-sieber.de/usbdlm.html

sofern das hier zutrifft ist's sogar Free:

<cite>

USBDLM ist Freeware für die private Nutzung sowie im Bildungs-Bereich, also Schulen, Unis usw. Eine Bildungs-Einrichtung gilt als solche, wenn dort Schüler, Studenten, Auszubildende in der Mehrheit sind...

Anderenfalls ist - nach einer 30-tägigen Testzeit - pro Computer eine Lizenz nötig, s.unten.

</cite>

Ansonsten braucht's das evtl. nur auf ausgewählten Workstations?

Schönen Gruß, Rudi.

Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Link to comment
Share on other sites

Auf Win 2000 Professional , XP und Vista gibt es noch eine Möglichkeit: Die Volume-GUID muttley

http://msdn.microsoft.com/en-us/library/aa364994(VS.85).aspx

$Buff = ""
For $i = 0 To 100
    $Buff &= " "
Next
$drives = DriveGetDrive("REMOVABLE")
For $i = 1 To $drives[0]
    $drives[$i] = StringUpper($drives[$i])
    $ret = DllCall("Kernel32.dll","long","GetVolumeNameForVolumeMountPoint","str",$drives[$i] & "\","str",$Buff,"dword",100)
    If Not @error And $ret[0] <> 0 Then
        ConsoleWrite($drives[$i] & " - GUID: " & $ret[2] & @CRLF)
    EndIf
Next

//Edit: With the DeviceID, I'm not sure. It could be, that the Mount-Point is in this string, too. So it could change, if you use an other USB-Port.

//Edit: A few UDfs to use the VolumeNames :

CODE
_ListVolumeNames()

Func _GetDriveByVolumeName($VolumeName,$Types="ALL")

Local $i,$ret, $drives,$Buff = ""

For $i = 0 To 100

$Buff &= " "

Next

$drives = DriveGetDrive($Types)

If @error Then Return SetError(@error,@extended,0)

For $i = 1 To $drives[0]

$drives[$i] = StringUpper($drives[$i])

$ret = DllCall("Kernel32.dll","long","GetVolumeNameForVolumeMountPoint","str",$drives[$i] & "\","str",$Buff,"dword",100)

If Not @error And $ret[0] <> 0 Then

If StringStripWS($ret[2],3) = $VolumeName Then Return $drives[$i]

EndIf

Next

Return SetError(2,0,"")

EndFunc

Func _GetVolumeNameByDrive($Drive)

If DriveStatus($Drive) = "INVALID" Or Not StringIsAlpha(StringLeft($Drive,1)) Then Return SetError(1,0,"")

$Drive = StringLeft($Drive,1) & ":\"

Local $ret,$Buff = ""

For $i = 0 To 100

$Buff &= " "

Next

$ret = DllCall("Kernel32.dll","long","GetVolumeNameForVolumeMountPoint","str",$Drive,"str",$Buff,"dword",100)

If Not @error And $ret[0] <> 0 Then

Return StringStripWS($ret[2],3)

EndIf

Return SetError(2,0,"")

EndFunc

#include <Array.au3>

Func _ListVolumeNames()

Local $drives = DriveGetDrive("ALL")

Local $list[$drives[0]+1][2] = [[$drives[0]]]

For $i = 1 To $drives[0]

$list[$i][0] = $drives[$i]

$list[$i][1] = _GetVolumeNameByDrive($drives[$i])

Next

_ArrayDisplay($list)

EndFunc

Edited by ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

Hi @all,

Hi Rudi, hi ProgAndi!

Your ideas, script examples and links are great and helps enormous.

@ProgAndi: Your script examples gives new ideas and maybe I will use now completely new scripts for my work in the youth organisation.

@Rudi: I have been contacted the author of USBDLM because of license in our youth organisation.

Greetings, horrscht

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...