PDA

View Full Version : How to get a drive-list?



ReneMiner
19-08-2015, 15:29
I wonder if there is a way to get a list of available drives attached to the users system.

The only current way i know is to test Dir_Exists("A:\" to "Z:\") but this will not find any network nor phones nor other devices.
In visual basic there was a hack to have some invisible Drive-List-Control which could be read out line by line.
There's no similar control available in thinBasic UI-module so this won't work here.

Does anyone know how to get a list of available drives? Is there some Win32-api-function or does anyone have some wrap for such?

ErosOlmi
20-08-2015, 01:20
You can use something like that.

GetLogicalDriveStrings (https://msdn.microsoft.com/en-us/library/windows/desktop/aa364975(v=vs.85).aspx) API function (GetLogicalDriveStringsA ASCII version) will fill a $NUL delimited/terminated string buffer with all currently valid drives in the system.

Ciao
Eros



'---Define the Function API
Declare Function GetLogicalDriveStrings Lib "Kernel32.dll" Alias "GetLogicalDriveStringsA" (ByVal nBufferLength As DWord, ByVal lpBuffer As DWord) As DWord


GetAllDrives


'----------------------------------------------------
Function GetAllDrives() As Long
'----------------------------------------------------
Local sBuffer As String
Local i As Integer
Local lBufferLen As Long
Local lDriveCount As Long

'---Get needed buffer lengh calling the function with zero
'---Plus 2 bytes used for last null termination, not considered into the returned len
lBufferLen = GetLogicalDriveStrings(0, %NULL) + 2

If lBufferLen Then
'---Prepare a long enough buffer
sBuffer = String$(lBufferLen, $NUL)

'---Get drives in sBuffer
GetLogicalDriveStrings(lBufferLen, StrPtr(sBuffer))

'---The format of sBuffer is like this -> "A:\" & $NUL "C:\" & $NUL "D:\" & $NUL "F:\" & $NUL & $NUL
'---A double $NUL is marking the end of buffer

'---Remove the last 2 $NUL
sBuffer = RTrim$(sBuffer, $NUL)

'---Count the items
lDriveCount = ParseCount(sBuffer, $NUL)

MsgBox 0, "You've got" & Str$(lDriveCount) & " drives on youre computer..!" & $CRLF & "Isn't that amazing?"

'---Show all items
For i = 1 To lDriveCount
MsgBox 0, Parse$(sBuffer, $NUL, i)
Next

End If

End Function

ReneMiner
20-08-2015, 09:47
thank you.
Ain't that worth to be added to file-module to work similar easy as Dir_ListArray maybe call it File_ListDrives?

ErosOlmi
20-08-2015, 10:54
Sure I will do.

ErosOlmi
21-08-2015, 13:43
Let me know if you like.
Attached thinBasic_File.dll module. Substitute the one you have into \thinBasic\Lib\

I've developed a Class module called cDrives. You can instantiate a class variable and then use it in this way:


Uses "file"
Uses "console"

Dim lCount As Long
Dim MyDrives As cDrives
MyDrives = New cDrives


PrintL "Drives present:", MyDrives.Count
PrintL "They are......:", MyDrives.ToString(",")


For lCount = 1 To MyDrives.Count
PrintL lCount, MyDrives.Get(lCount), MyDrives.GetType(lCount), MyDrives.GetType$(lCount)
Next


PrintL
PrintL "---Press a key to finish---"
WaitKey


I will further develop it adding more methods like: reload, size, free space, ...
If you have futher requests ... this is the time.

Petr Schreiber
22-08-2015, 09:27
Hi Eros,

tested on my PC, works perfectly :)

I was thinking about possible use cases, and came up with a bit of crazy ideas, please don't kill me :D

Idea #1
I did not find any use case when I would want to instantiate more than one instance - let's make it singleton!
While thinCore does not provide specific functions for singleton classes, it can be implemented as simple keyword with dot inside.

Drive.Count
Drive.Names(",") ' -- This was originally the ToString, its shorter and more descriptive
...

Idea #2
The convention used in lot of ThinBASIC functions is to use $ in function name returning string. So why not do it this way:
Drive.GetType(1) ' -- Returns integer
Drive.GetType$(1) ' -- Returns string

Idea #3
Most people are used to reference drive by letter, it is specified like this in paths too. This leads to idea of optional indexing by... name!
Drive("C").Type
Drive("C").Type$

Idea #4
I would love to have these functions available
.Size ' -- in bytes
.FreeSpace ' -- in bytes
.Exists

Idea #5
Let's bring the file module to gitHub! :)


Let me know, what you think about it,
Petr

Petr Schreiber
22-08-2015, 12:56
Hmm, it seems the Idea #1 would need some kind of adjustment in thinCore. One does not simply specify keyword with dot inside - I wanted to demonstrate the approach with simple example (http://www.thinbasic.com/community/showthread.php?12582-enVar-simple-module-for-handling-of-environment-variables), but it didn't work so I rolled back to classic procedural interface. Then I would propose Drive_ instead of Drive. prefix (it is the same in the end, ain't it :))


Petr

ReneMiner
23-08-2015, 18:16
Tried out but sadly it does not detect any smartphones nor any other path that does not follow the "A:\", "B:\"... pattern attached to my pc

ErosOlmi
23-08-2015, 22:54
Sorry Rene but I mislead your original request.
I didn't get you wanted a list of attached devices but I wrongly assumed devices = drives = disks.

Anyway, I do not have a reply at the moment because I assume your next request would be the possibility to list directories/files from that devices and maybe opening.
Actually I do know too much on that area to be able to have a complete reply. I need to document myself.

The following script will list all attached USB Hubs ... just in case it can help,



uses "WMI"
uses "OS"
uses "CONSOLE"

dim vData() as string
dim nItems as long
dim Counter as long
Dim ComputerName As String Value OS_GetComputerName
dim sBuffer as string


'---Ask data to WMI system


sBuffer = WMI_GetData(ComputerName, "", "", "", "Win32_USBHub", "", "DeviceID, Name, Description" )


'---Parse returned data into single lines
nItems = PARSE( sBuffer, vData(), $crlf)


'---Print lines
for Counter = 1 to nItems
PrintL vData(Counter)
next


'---Finished
PrintL "-----------------------------------------------------"
PrintL "Number of lines: " & nItems
PrintL "---------------------------Press a key to finish-----"
WaitKey




I attached a Phone to my Win10 USB, stored a text file in the phone SD card and tried to open that text file from some editor (Notepad++) but the file is first copied into IE cache and then opened read only in the editor.
I assume a direct file management from attached USB devices is not possible unless you copy files into a drive.

I will see if I can find something to let me understand better that area.

Ciao
Eros

ReneMiner
24-08-2015, 11:57
just back in mind to the above described hack for visual basic, using an invisible control to gather windows/system-information.

I know there must be some (File)Explorer-control (a treeview-control combined with a listview-control & attached image-list) built-in to Win32 but I don't know which library it is inside. purebasic does use it for sure as a built-in standard-control like a textbox, scrollbar etc.

Imagine to open a small, invisible window containing such explorer-control and to read out the content of the items inside the (listview-)control if requested- close the window and return results.
Could this be possible?

ReneMiner
16-10-2015, 20:35
...
I've developed a Class module called cDrives. You can instantiate a class variable and then use it...
...
I will further develop it adding more methods like: reload, size, free space, ...
If you have futher requests ... this is the time.

it would be cool if each variable of cDrives would have a "slot" to store a "current active path" on the actual drive for the user.
like


'...
Select Case myDrives.Get(lCount)
Case "C:\"
myDrives.Path(lCount, "C:\thinBasic\")

Case "D:\"
myDrives.Path(lCount, "D:\Music\")
' if there is no disc inside (invalid path) it would NOT store the assigned value
' .Path() would return empty string here

Case "E:\"
myDrives.Path(lCount, "E:\scripts\test\examples\we_will_kill_this\")

Case "F:\"
myDrives.Path(lCount, "F:\subfolder_does_not_exist\")
' this will store only "F:\" since the subfolder does not exist
'...


so .Path(lCount, sPath) would return the actual stored path-string

if calling Path(lCount) later without a path-parameter

for C:\-drive myDrives.Path(lCount) would return "C:\thinBasic\"

for D:\-Drive (DVD, no disc inside), myDrives.Path(lCount) would return "",
with Disc inside it would return the root "D:\" now

for E:\-Drive, it might return "E:\scripts\test\examples\" after we killed the subfolder