QB64 Phoenix Edition
Looking for a reliable way to determine if a drive letter is in use - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: Chatting and Socializing (https://qb64phoenix.com/forum/forumdisplay.php?fid=11)
+--- Forum: General Discussion (https://qb64phoenix.com/forum/forumdisplay.php?fid=2)
+--- Thread: Looking for a reliable way to determine if a drive letter is in use (/showthread.php?tid=1665)

Pages: 1 2 3


Looking for a reliable way to determine if a drive letter is in use - hanness - 05-08-2023

I'm looking for a reliable way to determine if a drive letter is in use but I'm running into some difficulties.

Take the following small clip as an example:

A$ = "F:\"
If _DirExists(A$) Then
    Print A$; " Exists"
Else
    Print A$; "Does not exist"
End If

Normally, this works fine and indicates if the drive letter contained in A$ exists. But now consider these two exceptions:

1) Suppose I have a thumbdrive attached to the system that has been wiped clean. By wiped clean, I mean you open DISKPART, select the thumbdrive, and perform a "CLEAN" on that drive. In this instance, there will be no partitions on the drive, but in File Explorer, the drive still shows up with a drive letter. However, the clip above will indicate that this drive letter does NOT exist. As a result, if I try to assign that drive letter to another drive, it will fail because it is already in use.

2) The same thing happens if I connect a drive that has BitLocker encryption but has not yet been unlocked. The QB64PE code will indicate that the drive letter does not exist even though it is already in use.

Any suggestions on a better way to determine if a drive letter is in use?


RE: Looking for a reliable way to determine if a drive letter is in use - bplus - 05-08-2023

Are we allowed to attempt to write onto the drive for our test?


RE: Looking for a reliable way to determine if a drive letter is in use - TerryRitchie - 05-08-2023

(05-08-2023, 03:46 PM)hanness Wrote: I'm looking for a reliable way to determine if a drive letter is in use but I'm running into some difficulties.

Take the following small clip as an example:

A$ = "F:\"
If _DirExists(A$) Then
    Print A$; " Exists"
Else
    Print A$; "Does not exist"
End If

Normally, this works fine and indicates if the drive letter contained in A$ exists. But now consider these two exceptions:

1) Suppose I have a thumbdrive attached to the system that has been wiped clean. By wiped clean, I mean you open DISKPART, select the thumbdrive, and perform a "CLEAN" on that drive. In this instance, there will be no partitions on the drive, but in File Explorer, the drive still shows up with a drive letter. However, the clip above will indicate that this drive letter does NOT exist. As a result, if I try to assign that drive letter to another drive, it will fail because it is already in use.

2) The same thing happens if I connect a drive that has BitLocker encryption but has not yet been unlocked. The QB64PE code will indicate that the drive letter does not exist even though it is already in use.

Any suggestions on a better way to determine if a drive letter is in use?

Just off the top of my head perhaps:

A$ = "F:\."

The period added will force a root directory check maybe?


RE: Looking for a reliable way to determine if a drive letter is in use - Ultraman - 05-08-2023

I can't remember the WinAPI way of doing this but it is far more accurate.


RE: Looking for a reliable way to determine if a drive letter is in use - Ultraman - 05-08-2023

Looks like you'd use GetLogicalDrives()

So,

Code: (Select All)
Declare CustomType Library
Function GetLogicalDrives~&()
End Declare

Dim As Unsigned Long currentLetters: currentLetters = GetLogicalDrives
'do something to figure out the bitmask using AND



RE: Looking for a reliable way to determine if a drive letter is in use - TerryRitchie - 05-08-2023

(05-08-2023, 03:55 PM)Ultraman Wrote: Looks like you'd use GetLogicalDrives()

So,

Code: (Select All)
Declare CustomType Library
Function GetLogicalDrives~&()
End Declare

Dim As Unsigned Long currentLetters: currentLetters = GetLogicalDrives
'do something to figure out the bitmask using AND

It looks like GetDriveTypeA may be more appropriate:

https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdrivetypea

It can report that a drive exists but no volume has been mounted.


RE: Looking for a reliable way to determine if a drive letter is in use - Ultraman - 05-08-2023

Well GetDriveTypeA would require that you call it multiple times with a different letter each time, whereas the other would be called only once and then you'd process the returned value.


RE: Looking for a reliable way to determine if a drive letter is in use - TerryRitchie - 05-08-2023

(05-08-2023, 04:05 PM)Ultraman Wrote: Well GetDriveTypeA would require that you call it multiple times with a different letter each time, whereas the other would be called only once and then you'd process the returned value.

It appears that GetLogicalDrives only sets a bit for the existence of a drive. His issue is he needs to know if a volume is mounted as well. Perhaps use GetLogicalDrives first to identify existing drives then use GetDriveTypeA on each detected drive for the existence of a volume.


RE: Looking for a reliable way to determine if a drive letter is in use - mnrvovrfc - 05-08-2023

On Linux this is ridiculously easy:

On Debian/Ubuntu check in "/media/(user)" for additional subdirectories.

On almost other Linux OS check in "/run/media/(user)".

Use _DIREXISTS for it.

There are no drive letters to worry about. However this depends whether or not the pluggable disk was given a volume label. If not then it becomes harder to track down an UUID to identify that disk. That UUID doesn't change if the disk is plugged into a different Linux OS or a different computer into a Linux OS.

Fiddling with certain programs (which require administrative privileges anyway) could do something about it. On most systems, however, GNOME Disk Utility does not require the "root" password to delete partitions and reformat disks! Be careful out there.



What is the result of "vol F:" on the terminal on Windows?


RE: Looking for a reliable way to determine if a drive letter is in use - Steffan-68 - 05-08-2023

I found something else in my hodgepodge, maybe that can help.  Wink


Code: (Select All)
'LETTER_OF_USB_DEVICE  'program by Euklides
'Working with files on USB devices

'When you write a program using files located on USB drives, you don't be
'sure that the letter of this drive is always the same.
'You cannot write for instance:

'         OPEN "F:\MYFILE\info.txt" FOR INPUT AS #1
'         ...

'If your drive has a new letter, for instance "E", you must go into your program
' and change the letter
'So what you can do is this:

'1) '  find the serial of your drive
'  Use below:

'         GOSUB SERIALSSHOW

'  and you will see all the serials of then actuel connected drives
'  For instance, the good drive has the serial "<9911-447E>

'2) Now write your program so:

'        fic$ = "<9911-447E>:\MYFILE\info.txt"
'        GOSUB DRIVELETTERFIND: IF _CLIPBOARD$ = "" THEN PRINT "USB unit is not connected for using " + fic$: END
'        fic$ = _CLIPBOARD$:OPEN fic$ FOR INPUT AS #1
'       ...


'End


'=====================================================================
Declare Dynamic Library "kernel32"
FUNCTION GetVolumeInformationA& (lpRootPathName$, lpVolumeNameBuffer$, BYVAL nVolumeNameSize~&, _
    lpVolumeSerialNumber~&, lpMaximumComponentLength~&, lpFileSystemFlags~&, lpFileSystemNameBuffer$, BYVAL nFileSystemNameSize&)
End Declare
Declare Library: Function GetDriveType& (d$): End Declare
Dim Shared DriveType As String, SERIALFOUND As String
'---
SERIALSSHOW:
For q = 1 To 26: X = GetFileInfo(q): If SERIALFOUND <> "<!!!-!!!>" Then Print " "; Chr$(64 + q) + ":    "; SERIALFOUND
Next q
End
'---
DRIVELETTERFIND: 'in-->fic$ like' "<SER-IAL>ficname"  out--> like "D:\ficname"
_Clipboard$ = "": K$ = UCase$(Left$(fic$, 2))
If Right$(K$, 1) = ":" And Left$(K$, 1) >= "A" And Left$(K$, 1) <= "Z" And DRIVEEXISTS(Asc(K$) - 64) = 1 Then _Clipboard$ = fic$: Return
J1 = InStr(fic$, "<"): J2 = InStr(J1, fic$, ">")
If J1 = 0 Or J2 = 0 Then Print fic$; " must be written like: <serial>\ficmame...": End
Serialsearch$ = Mid$(fic$, J1, J2 - J1 + 1): q = 0
For q = 1 To 26: X = GetFileInfo(q)
    If SERIALFOUND = Serialsearch$ Then
        fic$ = Right$(fic$, Len(fic$) - J2): If Left$(fic$, 1) <> ":" Then fic$ = ":" + fic$
        fic$ = Chr$(64 + q) + fic$: _Clipboard$ = fic$
    End If
Next q
Return
'---
Function GetFileInfo (D)
    SERIALFOUND = "<!!!-!!!>":
    If DRIVEEXISTS(D) <> 1 Then GetFileInfo = 0: Exit Function
    Dname$ = Chr$(D + 64) + ":\": Sname$ = Space$(260)
    R = GetVolumeInformationA(Dname$ + Chr$(0), Vname$, 260, serial~&, empty1~&, empty2~&, Sname$, 260)
    If R = 0 Then Exit Function
    Sname$ = Left$(Hex$(serial~&), 4) + "-" + Right$(Hex$(serial~&), 4)
    SERIALFOUND = "<" + Sname$ + ">"
    GetFileInfo = -1
End Function
'---
Function DRIVEEXISTS (V)
    DRIVEEXISTS = 0: varX$ = Chr$(V + 64) + ":\" + Chr$(0): VarX = GetDriveType(varX$): If VarX > 1 Then DRIVEEXISTS = 1
End Function
'=====================================================================


   

My Pc Drives

C: is a Drive
D: Partition on C:
E: Partition on F:
F: is a Drive
G: is a USB Stick