blindwig Posted June 7, 2005 Posted June 7, 2005 I have a need to get a list of USB-attached drives on my system. I couldn't find any AutoIt functions to do this, and I don't know how to do any system calls or anything fancy, so I ended up writing a script to interface with DISKPART.EXE, a command-line tool for managing disks. This script obviously won't work on a system that does not have access to DISKPART.EXE This function returns an [x][2] array, where [x][0]=drive number and [x][1]=drive size. The length of the array is in [0][0] Notice that I return drive numbers, not letters. Letters are too ambigious - a physical drive can have multiple letters (partitions), no letter (if windows doesn't recognise the file system, or if it's letter has been removed), or a letter can represent multiple physical drives (spanned or stripped volumes). Also note that drive numbers are 0-based. CODE Func DriveGetUsbList() dim $i, $temp ;Step 1 - Get all valid drive numbers Dim $DriveListNum[100][2], $DriveListNext=1, $DriveListText ;$DriveListNum is a table of valid drive numbers and their sizes, $DriveListNext is an index to the next free entry ;$DriveListText is a temporary variable used for parsing text in and out $DriveListText=StringSplit(RunGetOutput(@ComSpec & " /c echo list disk | diskpart"), @CRLF) For $i = 1 to $DriveListText[0] if StringInStr($DriveListText[$i], "Disk ") Then $Temp = StringMid($DriveListText[$i],8,3) if $Temp<>"###" Then $DriveListNum[$DriveListNext][0] = Int($Temp) $DriveListNum[$DriveListNext][1] = StringMid($DriveListText[$i],25,7) $DriveListNext = $DriveListNext + 1 EndIf If $DriveListNext > Ubound($DriveListNum) Then Redim $DriveListNum[ubound($DriveListNum)+20][2] EndIf Next $DriveListNum[0][0]=$DriveListNext ;Element [0][0] contains the list size (1-based) ;Step 2 - figure out which are attached via USB Dim $TempFile, $hndFile_Temp, $DriveUsbCur ;Step 2.1 - build a script for DiskPart $TempFile = _TempFile() $hndFile_Temp = FileOpen($TempFile, 2) for $i = 1 to $DriveListNext - 1 FileWriteLine($hndFile_Temp, "Select Disk " & $DriveListNum[$i][0]) FileWriteLine($hndFile_Temp, "Detail Disk") Next FileClose($hndFile_Temp) ;Step 2.2 - execute the script for DiskPart $DriveListText=StringSplit(RunGetOutput(@ComSpec & " /c echo list disk | diskpart < " & $TempFile), @CRLF) ;Step 2.3 - parse the results, build a list of USB drives Dim $DriveListUsb[$DriveListNext-1][2] $DriveListNext=1 For $i = 1 to $DriveListText[0] if StringRight($DriveListText[$i], 26) = ' is now the selected disk.' Then $DriveUsbCur = StringSection($DriveListText[$i], 2, " ") EndIf if $DriveListText[$i] = 'Type : USB' Then $DriveListUsb[$DriveListNext][0] = $DriveUsbCur $DriveListUsb[$DriveListNext][1] = TableLookUp($DriveListNum, $DriveUsbCur) $DriveListNext = $DriveListNext + 1 EndIf Next $DriveListUsb[0][0]=$DriveListNext-1 ;Step 3 - Return the results table If $DriveListUsb[0][0] > 0 Then Redim $DriveListUsb[$DriveListUsb[0][0]+1][2] Return $DriveListUsb Else Return 0 EndIf EndFunc My UDF Threads:Pseudo-Hash: Binary Trees, Flat TablesFiles: Filter by Attribute, Tree List, Recursive Find, Recursive Folders Size, exported to XMLArrays: Nested, Pull Common Elements, Display 2dSystem: Expand Environment Strings, List Drives, List USB DrivesMisc: Multi-Layer Progress Bars, Binary FlagsStrings: Find Char(s) in String, Find String in SetOther UDF Threads I Participated:Base64 Conversions
w0uter Posted June 7, 2005 Posted June 7, 2005 pardon me for asking. but wtf is: RunGetOutput My UDF's:;mem stuff_Mem;ftp stuff_FTP ( OLD );inet stuff_INetGetSource ( OLD )_INetGetImage _INetBrowse ( Collection )_EncodeUrl_NetStat_Google;random stuff_iPixelSearch_DiceRoll
blindwig Posted June 7, 2005 Author Posted June 7, 2005 pardon me for asking. but wtf is:RunGetOutput<{POST_SNAPBACK}>Oops, forgot to include that. It's another function I wrote that will run a command (intended for console-mode commands) that will return the output in a string.Here's the code:CODEFunc RunGetOutput($CommandLine) Dim $Tempfile, $Return ;Find a temp file. Could use _TempFile() instead, if file.au3 is included Do $TempFile = @TempDir & '\' & Int(Random(65536)) & '.txt' Until not FileExists($TempFile) ;Run the inputted command, redirect output to our tempfile RunWait($CommandLine & " > " & $TempFile, '', @SW_HIDE) ;Read the temp file into a string, delete the temp file, return the string $Return = FileRead($TempFile, FileGetSize($TempFile)) FileDelete($TempFile) Return $ReturnEndFunc My UDF Threads:Pseudo-Hash: Binary Trees, Flat TablesFiles: Filter by Attribute, Tree List, Recursive Find, Recursive Folders Size, exported to XMLArrays: Nested, Pull Common Elements, Display 2dSystem: Expand Environment Strings, List Drives, List USB DrivesMisc: Multi-Layer Progress Bars, Binary FlagsStrings: Find Char(s) in String, Find String in SetOther UDF Threads I Participated:Base64 Conversions
CyberSlug Posted June 7, 2005 Posted June 7, 2005 Where are StringSection and TableLookUp defined?I did something somewhat-related a while back, but your code looks much cleanerhttp://www.autoitscript.com/forum/index.ph...wtopic=8704&hl= Use Mozilla | Take a look at My Disorganized AutoIt stuff | Very very old: AutoBuilder 11 Jan 2005 prototype I need to update my sig!
blindwig Posted June 7, 2005 Author Posted June 7, 2005 Where are StringSection and TableLookUp defined?<{POST_SNAPBACK}>StringSection is like StringSplit(), except that instead of returning the entire array, it just returns the section that you want. Here's the code:CODEFunc StringSection($Input, $Number, $Seperator="|") ;Returns a substring of $Input, between $Number and $Number+1 occurance of $Seperator $Number=Int($Number) If $Number>0 And $Number<=StringInCount($Input, $Seperator)+1 Then If $Number=1 Then $Begin=0 $End=StringInStr($Input, $Seperator, 0, 1) Else $Begin=StringInStr($Input, $Seperator, 0, $Number-1) $End=StringInStr($Input, $Seperator, 0, $Number) If @error Then $End=StringLen($Input)+1 EndIf Return StringMid($Input, $Begin+1, $End-$Begin-1) Else Return "" EndIfEndFuncTableLookUp looks at an array[x][2] and returns the value of [x][1] such that [x][0] matches the given key.This is the predecessor to my table library:http://www.autoitscript.com/forum/index.php?showtopic=12136Here's the old code:CODEFunc TableLookUp($Table, $Key) ;$Table is an array of [x][1]. Function finds a record such that $Key=$Table[x][0] and returns $Table[x][1] If UBound($Table, 0)<2 Then Return "" For $i=0 to UBound($Table, 1)-1 If $Table[$i][0]=$Key Then Return $Table[$i][1] Next Return ""EndFuncI'm glad you think my code is clean. This is probably one of the first things I wrote with AutoIt, and looking at it now I see plenty of room for improvement My UDF Threads:Pseudo-Hash: Binary Trees, Flat TablesFiles: Filter by Attribute, Tree List, Recursive Find, Recursive Folders Size, exported to XMLArrays: Nested, Pull Common Elements, Display 2dSystem: Expand Environment Strings, List Drives, List USB DrivesMisc: Multi-Layer Progress Bars, Binary FlagsStrings: Find Char(s) in String, Find String in SetOther UDF Threads I Participated:Base64 Conversions
blindwig Posted June 8, 2005 Author Posted June 8, 2005 OK, I totally re-wrote the routine. Now it returns a table containing a list of all drives, keyed by drive number, and containing a CSV field with all the drive details. Again, this relies on shelling out to run DISKPART, so it is dependant on that.Function _DriveGetList() takes no input, and if successful, returns a table containing the drive info, keyed by drive numberCODEFunc _DriveGetList() Dim $EOF Dim $DriveNum, $DriveDetails, $Detail Dim $ReadLine, $RetVal Dim $OutputFileName, $hndFile_Output Dim $InputFileName, $hndFile_Input Dim $tblDriveList Dim $i, $DriveNums ;Find names for temporary output files Do $OutputFileName = @TempDir & '\' & Int(Random(65536)) & '.txt' Until not FileExists($OutputFileName) Do $InputFileName = @TempDir & '\' & Int(Random(65536)) & '.txt' Until not FileExists($InputFileName) ;Write drive list to output file $RetVal=RunWait(@COMSPEC & ' /c echo list disk | diskpart>' & $OutputFileName,'',@SW_HIDE) If $RetVal Then Return '' ;Read output, parse to find drive list _TableCreate($tblDriveList) $hndFile_Output=FileOpen($OutputFileName,0) $ReadLine = FileReadLine($hndFile_Output) $EOF = @error While Not $EOF While (StringMid($ReadLine, 3, 5) <> 'Disk ' Or StringMid($ReadLine, 8, 3)='###') And Not $EOF $ReadLine = FileReadLine($hndFile_Output) $EOF = @error WEnd If Not $EOF Then $DriveNum=StringStripWS(StringMid($ReadLine, 8, 3), 3) $DriveDetails=StringStripWS(StringMid($ReadLine, 13, 10), 3) $DriveDetails=$DriveDetails & ',' & StringStripWS(StringMid($ReadLine, 25, 7), 3) $DriveDetails=$DriveDetails & ',' & StringStripWS(StringMid($ReadLine, 34, 7), 3) $DriveDetails=$DriveDetails & ',' & StringStripWS(StringMid($ReadLine, 43, 3), 3) $DriveDetails=$DriveDetails & ',' & StringStripWS(StringMid($ReadLine, 43, 3), 3) _TableSetValue($tblDriveList, $DriveNum, $DriveDetails) $ReadLine = FileReadLine($hndFile_Output) EndIf WEnd FileClose($hndFile_Output) ;Build a script to get extended drive info $DriveNums=_TableGetKeys($tblDriveList) $hndFile_Input = FileOpen($InputFileName,2) For $i = 1 To $DriveNums[0] FileWriteLine($hndFile_Input, 'select disk ' & $DriveNums[$i]) FileWriteLine($hndFile_Input, 'detail disk') Next FileClose($hndFile_Input) ;Run script, save output $RetVal=RunWait(@COMSPEC & ' /c echo list disk | diskpart /s ' & $InputFileName & '>' & $OutputFileName,'',@SW_HIDE) FileDelete($InputFileName) If $RetVal Then Return '' ;Parse output, look for extended info $hndFile_Output=FileOpen($OutputFileName,0) $DriveNum=-1 $ReadLine = FileReadLine($hndFile_Output) $EOF = @error While Not $EOF $Detail = StringLeft($ReadLine, 9) ;look for a new drive number If StringInStr($ReadLine, ' is now the selected disk.') Then ;if switching drives, then need to write details from the last drive to the table If $DriveNum>=0 Then _TableSetValue($tblDriveList, $DriveNum, $DriveDetails) EndIf ;Get a new drive number, get details for that drive $DriveNum = StringStripWS(StringMid($ReadLine, 6, 2), 3) $DriveDetails = _TableGetValue($tblDriveList, $DriveNum) ;skip a line $ReadLine = FileReadLine($hndFile_Output) $EOF = @error ;next line should be the drive name If Not $EOF Then $ReadLine = FileReadLine($hndFile_Output) $EOF = @error $DriveDetails = $DriveDetails & ',' & $ReadLine EndIf EndIf ;look for details about the current drive If _StringInSet($Detail,'Disk ID: ,Type : ,Bus : ,Target : ,LUN ID : ') Then $DriveDetails = $DriveDetails & ',' & StringMid($ReadLine, 10) EndIf $ReadLine = FileReadLine($hndFile_Output) $EOF = @error WEnd ;Write remaining details to the table If $DriveNum>=0 Then _TableSetValue($tblDriveList, $DriveNum, $DriveDetails) EndIf FileClose($hndFile_Output) FileDelete($OutputFileName) Return $tblDriveListEndFuncFunc _DriveGetListUSB($tblDrives) Dim $tblDrives, $DriveNums, $DriveDetails, $i If Not _TableIsValid($tblDrives) Then $tblDrives = _DriveGetList() $DriveNums = _TableGetKeys($tblDrives) Dim $UsbList[$DriveNums[0]+1] $UsbList[0]=1 For $i = 1 to $DriveNums[0] $DriveDetails = StringSplit(_TableGetValue($tblDrives,$DriveNums[$i]), ',') If UBound($DriveDetails)>=7 Then If $DriveDetails[8]='USB' Then $UsbList[$UsbList[0]]=$DriveNums[$i] $UsbList[0] = $UsbList[0] + 1 EndIf EndIf Next Redim $UsbList[$UsbList[0]] $UsbList[0] = $UsbList[0] - 1 Return $UsbListEndFuncFunction _DriveGetListUSB will return an array containing the numbers of USB drives. It will take a table returned by _DriveGetList(), or will generate a fresh one.CODEFunc _DriveGetListUSB($tblDrives = -1) Dim $tblDrives, $DriveNums, $DriveDetails, $i If Not _TableIsValid($tblDrives) Then $tblDrives = _DriveGetList() $DriveNums = _TableGetKeys($tblDrives) Dim $UsbList[$DriveNums[0]+1] $UsbList[0]=1 For $i = 1 to $DriveNums[0] $DriveDetails = StringSplit(_TableGetValue($tblDrives,$DriveNums[$i]), ',') If UBound($DriveDetails)>=7 Then If $DriveDetails[8]='USB' Then $UsbList[$UsbList[0]]=$DriveNums[$i] $UsbList[0] = $UsbList[0] + 1 EndIf EndIf Next Redim $UsbList[$UsbList[0]] $UsbList[0] = $UsbList[0] - 1 Return $UsbListEndFuncBoth of these functions require my tables UDF and my _StringInSet() function. My UDF Threads:Pseudo-Hash: Binary Trees, Flat TablesFiles: Filter by Attribute, Tree List, Recursive Find, Recursive Folders Size, exported to XMLArrays: Nested, Pull Common Elements, Display 2dSystem: Expand Environment Strings, List Drives, List USB DrivesMisc: Multi-Layer Progress Bars, Binary FlagsStrings: Find Char(s) in String, Find String in SetOther UDF Threads I Participated:Base64 Conversions
Wus Posted June 9, 2005 Posted June 9, 2005 (edited) i dont suppose youd be willing top make a zip of all of your udf's and pst em? some look very useful... perty plz Edited June 9, 2005 by Wus
Westi Posted June 11, 2005 Posted June 11, 2005 i dont suppose youd be willing top make a zip of all of your udf's and pst em? some look very useful...YES
blindwig Posted June 13, 2005 Author Posted June 13, 2005 i dont suppose youd be willing top make a zip of all of your udf's and pst em? some look very useful...perty plz <{POST_SNAPBACK}>Right now they're mostly works in progress. As I complete a function I post it here for some peer review. Maybe once I have a good collection of functions that form a logical module I'll post it up here. But if you like my work, just do a search for my name and UDF in the title. My UDF Threads:Pseudo-Hash: Binary Trees, Flat TablesFiles: Filter by Attribute, Tree List, Recursive Find, Recursive Folders Size, exported to XMLArrays: Nested, Pull Common Elements, Display 2dSystem: Expand Environment Strings, List Drives, List USB DrivesMisc: Multi-Layer Progress Bars, Binary FlagsStrings: Find Char(s) in String, Find String in SetOther UDF Threads I Participated:Base64 Conversions
jzn2 Posted September 24, 2006 Posted September 24, 2006 (edited) could you also retrieve a drive letter or perhaps a list of drive letters?or can an optical drive be called by the drive number? as i do here: CDTray("F:", "close") Edit: Also, I am asuming that Func _DriveGetList() is not dependent upon Func _DriveGetListUSB and visa versa is that correct? Edited September 25, 2006 by jzn2
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now