Recent

Author Topic: show available drives [SOLVED]  (Read 545 times)

bjlockie1

  • New member
  • *
  • Posts: 8
show available drives [SOLVED]
« on: November 20, 2020, 10:20:24 pm »
I'm trying to list available drives.
These functions show 3 letters, C, D, Z.
It can't ChDir to drive D:\ but C:\ and Z:\ work fine.
I don't think drive D: should be listed.
I am not a Windows programmer so I cobbled this code together.


Code: Pascal  [Select][+][-]
  1. function GetBit(Value: QWord; Index: Byte): Boolean;
  2. begin
  3.   Result := ((Value shr Index) and 1) = 1;
  4. end;
  5.  
  6. function GetDriveLetters(): TStringList;
  7. {$ifdef Windows}
  8. var dword     : QWord;
  9.     letter    : Char;
  10.     i         : Byte = 0;
  11.     shortname : String;
  12. {$endif}
  13. begin
  14.     Result:=TStringList.Create();
  15.     {$ifdef Windows}
  16.         dword:=GetLogicalDrives();
  17.  
  18.         for letter:='A' to 'Z' do
  19.         begin
  20.             if GetBit(dword,i)=True then
  21.             begin
  22.                 shortname:='(DRIVE) '+letter+':\';
  23.                 Result.Add( shortname );
  24.             end;
  25.             i:=i+1;
  26.         end;
  27.     {$endif}
  28. end;
« Last Edit: November 22, 2020, 04:29:52 am by bjlockie1 »

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 837
    • Lebeau Software
Re: show available drives
« Reply #1 on: November 20, 2020, 10:24:27 pm »
It can't ChDir to drive D:\ but C:\ and Z:\ work fine.

What kind of drive is D:\ exactly?  What does GetDriveType() report for it?  Is it a partition on an HDD/SSD?  Is it a CD/DVD disc drive?  Is it a removable USB drive?  Is it a network drive share?
« Last Edit: November 23, 2020, 07:23:22 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

440bx

  • Hero Member
  • *****
  • Posts: 2048
Re: show available drives
« Reply #2 on: November 21, 2020, 02:12:53 am »
I'm trying to list available drives.
These functions show 3 letters, C, D, Z.
It can't ChDir to drive D:\ but C:\ and Z:\ work fine.
I don't think drive D: should be listed.
The fact that Windows allocated a letter to a drive does not always imply the drive is accessible.  That's why @Remy Lebeau above was asking for the drive type.

You can find an example of showing the available drives and their type at https://forum.lazarus.freepascal.org/index.php/topic,44377.msg311910.html#msg311910

But, again, the fact that a letter/drive is listed does _not_ mean it is accessible.

HTH.
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

winni

  • Hero Member
  • *****
  • Posts: 2009
Re: show available drives
« Reply #3 on: November 21, 2020, 02:32:58 am »
I'm trying to list available drives.


Why do you start a new topic with the same issue
while the other topic is still active??


bjlockie1

  • New member
  • *
  • Posts: 8
Re: show available drives
« Reply #4 on: November 21, 2020, 05:32:45 am »
Why do you start a new topic with the same issue
while the other topic is still active??

The other topic was in the Linux forum.
I said I was coming here to hopefully get more Windows specific help.
Was that wrong?

bjlockie1

  • New member
  • *
  • Posts: 8
Re: show available drives
« Reply #5 on: November 21, 2020, 05:34:46 am »
It can't ChDir to drive D:\ but C:\ and Z:\ work fine.

What kind of drive is D:\ exactly?  What does GetDriveType() report for it?  Is it a partition on an HDD/SSD?  Is it a CD/DVD drive that doesn't have a disc in it?  Is it a removable USB drive?


C -> 3
D -> 5
Z -> 4

D is probably an empty cdrom. :-)

Code: Pascal  [Select][+][-]
  1. function GetDriveLetters(): TStringList;
  2. {$ifdef Windows}
  3. var dword     : QWord;
  4.     letter    : Char;
  5.     i         : Byte = 0;
  6.     shortname : String;
  7.     dr        : Packed array[0..3] of char;
  8.     dt        : UINT;
  9. {$endif}
  10. begin
  11.     Result:=TStringList.Create();
  12.     {$ifdef Windows}
  13.         ZeroMemory(@dr, sizeof(dr));
  14.         lstrcpy(dr, 'A:\');    
  15.  
  16.         dword:=GetLogicalDrives();
  17.  
  18.         for letter:='A' to 'Z' do
  19.         begin
  20.             if GetBit(dword,i)=True then
  21.             begin
  22.                 dr[0]:=char(ord('A')+i);
  23.                 dt:=GetDriveType(dr);
  24.                 shortname:='(DRIVE) '+letter+':\' + IntToStr(dt);
  25.                 Result.Add( shortname );
  26.             end;
  27.             inc(i);
  28.         end;
  29.     {$endif}
  30. end;    
« Last Edit: November 21, 2020, 05:45:09 am by bjlockie1 »

Bart

  • Hero Member
  • *****
  • Posts: 4040
    • Bart en Mariska's Webstek
Re: show available drives
« Reply #6 on: November 21, 2020, 04:47:37 pm »
I showed you simple code how to do that in https://forum.lazarus.freepascal.org/index.php/topic,52203.msg384399.html#msg384399

Use the function GetAvailableDrives(DiskMustBeInDrive: Boolean = False): TSysCharSet; function.
Set the DiskMustBeInDrive parameter to True.

If there is no disc in the CDRom, it wont be included in the resulting set.

Bart

Bart

  • Hero Member
  • *****
  • Posts: 4040
    • Bart en Mariska's Webstek
Re: show available drives
« Reply #7 on: November 21, 2020, 05:44:06 pm »
I'll make it even simpler for you.
Download http://svn.code.sf.net/p/flyingsheep/code/trunk/MijnLib/fsiwinutils.pp

Now you can do things like this
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   Drives: TSysCharSet;
  4.   D: Char;
  5. begin
  6.   writeln('Reported drives by Windows:');
  7.   Drives := GetAvailableDrives(False);
  8.   for D in Drives do writeln(D + ':\',' [',DiskInDrive(D),']');
  9.   writeln;
  10.   writeln('Actual mounted drives:');
  11.   Drives := GetAvailableDrives(True);
  12.   for D in Drives do writeln(D + ':\');
  13.   writeln;
  14.   writeln('Removable drives:');
  15.   Drives := GetAvailableDrives(False, [dtRemovable]);
  16.   for D in Drives do writeln(D + ':\');
  17.   writeln;
  18.   writeln('CD-Roms''s:');
  19.   Drives := GetAvailableDrives(False, [dtCDROM]);
  20.   for D in Drives do writeln(D + ':\');
  21.   writeln;
  22.   writeln('Actual mounted CD-Roms''s:');
  23.   Drives := GetAvailableDrives(True, [dtCDROM]);
  24.   for D in Drives do writeln(D + ':\');
  25.   writeln;
  26. end;[code]
  27.  
  28. For me it outputs:
  29. [code]
  30. Reported drives by Windows:
  31. C:\ [TRUE]
  32. D:\ [TRUE]
  33. E:\ [FALSE]
  34. F:\ [TRUE]
  35.  
  36. Actual mounted drives:
  37. C:\
  38. D:\
  39. F:\
  40.  
  41. Removable drives:
  42. F:\
  43.  
  44. CD-Roms's:
  45. E:\
  46.  
  47. Actual mounted CD-Roms's:
  48.  

Bart

bjlockie1

  • New member
  • *
  • Posts: 8
catch exception around ChDir
« Reply #8 on: November 22, 2020, 02:05:35 am »
I thought I could wrap ChDir in a try but I still get exception class 'RunError(152)'.


Code: Pascal  [Select][+][-]
  1. procedure ChangeDir( dirname : String );
  2. begin
  3.     try
  4.         ChDir( dirname );
  5.     except
  6.         ShowMessage('Can''t change to '''+dirname+'''');
  7.     end;
  8. end;    

bjlockie1

  • New member
  • *
  • Posts: 8
Re: show available drives
« Reply #9 on: November 22, 2020, 04:29:32 am »
I turned off the debugging and ran it from outside the IDE and the try catches the exception.

 

TinyPortal © 2005-2018