Board index » delphi » Catching drive not ready

Catching drive not ready

I am working on an application in which I use the drive combo,
directory list and file list boxes in coordination.  For the most part,
the application works real well.  One small problem, if I select a
drive (say B, a floppy drive) that has no disk in it, I get this lovely
system message saying 'Drive not ready'.  I got a solution to that
message which seems to work okay as well.

Rslt := SetErrorMode(SEM_FAILCRITICALERRORS);

I placed this statement in the OnCreate event for the form in question.
Now I no longer get that lovely system message, but I would like a way
to trap the exception so the error that I now get from Delphi is a
little more pleasant to the user.  The current message is 'Invalid
filename'.  Not real good.

It would seem that I would be able to trap this exception (EInOutError)
in a Try...Except set of statements, but I sure can't seem to find the
correct spot/handler in which this should be handled.  Any
suggestions??  (I always prefer examples, but I'll take suggestions)

I WILL post a solution that seems to perform acceptably to me when I
either figure it out or someone posts or EMails it to me.  (Someone got
the VCL source for the above mentioned drive/directory/file boxes that
might be able to help me out?)

Thanks for your help on this one.  

--
Regards,
Eric Drews                      Custom applications
Drews Enterprises               Data conversion
908 665 2513                    Hardware consulting
drews...@superlink.net          Using: Pick, Pick-like systems & Delphi

 

Re:Catching drive not ready


Quote
drews...@superlink.net (Eric Drews) wrote:
>One small problem, if I select a
>drive (say B, a floppy drive) that has no disk in it, I get this lovely
>system message saying 'Drive not ready'.

Piper  Keairnes 73241,1540  posted the following source code on
Compuserve a while ago.  It seems to work well.   Piper placed the
code in the public domain.

unit DiskUtil;

interface

function DiskCheck( DriveLetter: char ): boolean;
function DiskCheckWithInsert( DriveLetter: char ): boolean;
function DriveValid( DriveLetter: char): boolean;

implementation

uses
  SysUtils, WinProcs, WinTypes, Forms, Controls, Dialogs, FileCtrl;

function DiskCheck( DriveLetter: char ): boolean;
var
  oldMode: cardinal;
begin
  if DriveLetter in ['a'..'z'] then
    Dec(DriveLetter, $20);
  if not (DriveLetter in ['A'..'Z']) then
    raise EConvertError.Create('Invalid drive id: ' + DriveLetter);
  oldMode := SetErrorMode( SEM_FAILCRITICALERRORS );
  try
    Result := not (DiskSize(Ord(DriveLetter) - $40) = -1);
  finally
    SetErrorMode(oldMode);
  end;
end;

function DiskCheckWithInsert( DriveLetter: char ): boolean;
var
  oldCursor: TCursor;
begin
  Result := True;
  oldCursor := Screen.Cursor;
  Screen.Cursor := crHourglass;
  try
    while not DiskCheck(DriveLetter) do
      begin
        Screen.Cursor := crDefault;
        if MessageDlg( 'Insert a formatted disk in drive ' +
                       UpperCase(DriveLetter) +
                       ' then press OK.', mtConfirmation,
                       [mbOK,mbCancel], 0) = mrCancel then
          begin
            Result := False;
            Exit;
          end;
        Screen.Cursor := crHourglass;
      end;
  finally
    Screen.Cursor := oldCursor;
  end;
end;

function DriveValid( DriveLetter: char): boolean;
var
  ret: integer;
begin
  if DriveLetter in ['a'..'z'] then
    Dec(DriveLetter, $20);
  if not (DriveLetter in ['A'..'Z']) then
    raise EConvertError.Create('Invalid drive id: ' + DriveLetter);
  ret := GetDriveType(Ord(DriveLetter) - $41);
  Result := ret <> 0;
end;

end.

Re:Catching drive not ready


In article <4g12ba$...@lunar.eclipse.net>, mhazl...@eclipse.net says...
Quote

>drews...@superlink.net (Eric Drews) wrote:

>>I am working on an application in which I use the drive combo,
>>directory list and file list boxes in coordination.  For the most
part,
>>the application works real well.  One small problem, if I select a
>>drive (say B, a floppy drive) that has no disk in it, I get this
lovely
>>system message saying 'Drive not ready'.  I got a solution to that
>>message which seems to work okay as well.

>>Rslt := SetErrorMode(SEM_FAILCRITICALERRORS);

>I got this rou{*word*249} from borlands web site.

>Q:  How can I check to see if there is a disk in the "A" drive
>    without an error message box telling you that it is not ready?

>A:  The following function accepts a drive letter as a parameter,
>    and it will return a boolean value that indicates whether
>    or not there is a disk in the drive.

>function DiskInDrive(Drive: Char): Boolean;
>var
>  ErrorMode: word;
>begin
>  { make it upper case }
>  if Drive in ['a'..'z'] then Dec(Drive, $20);
>  { make sure it's a letter }
>  if not (Drive in ['A'..'Z']) then
>    raise EConvertError.Create('Not a valid drive ID');
>  { turn off critical errors }
>  ErrorMode := SetErrorMode(SEM_FailCriticalErrors);
>  try
>    { drive 1 = a, 2 = b, 3 = c, etc. }
>    if DiskSize(Ord(Drive) - $40) = -1 then
>      Result := False
>    else
>      Result := True;
>  finally
>    { restore old error mode }
>    SetErrorMode(ErrorMode);
>  end;
>end;

>Hope thats not what you are presently doing :>  I see no where to set
>a "custom" message so it may not be a big help.

Matthew,

Thanks for the post on the drive not ready.  The one problem that I
have is that the error checking needs to be integrated into the
TDriveComboBox component.  The problem occurs when a user changes the
drive in the combobox that (in this case at least) is a floppy drive
containing no diskette.  I suppose one might be able to hang your
routine on the OnChange event and possibly get away with that solution.
 I'll give that a shot and see if it will work.  Thanks again for your
post.
--
Regards,
Eric Drews
Drews Enterprises
908 665 2513
drews...@superlink.net

Re:Catching drive not ready


Quote
drews...@superlink.net (Eric Drews) wrote:
>In article <4g12ba$...@lunar.eclipse.net>, mhazl...@eclipse.net says...

>>drews...@superlink.net (Eric Drews) wrote:

[snip..]

Quote
>Thanks for the post on the drive not ready.  The one problem that I
>have is that the error checking needs to be integrated into the
>TDriveComboBox component.  The problem occurs when a user changes the
>drive in the combobox that (in this case at least) is a floppy drive
>containing no diskette.  I suppose one might be able to hang your
>routine on the OnChange event and possibly get away with that solution.
> I'll give that a shot and see if it will work.  Thanks again for your
>post.

You will find that the error occurs BEFORE change is called.  I see three
possible solutions.

1) Create your own DriveComboBox and override the Click procedure.  Then in your
Click do the function describe above. If a disk is not id the drive but the
index back.  It would be nice to have a "Test for Valid Drives" property that
enables this. {see code below}

2) Create your own DriveComboBox and override the BuildList procedure.  Then in
your BuildList do the function describe above removing all non-valid drives.

3) Before calling your dialog, test each drive listed in the ComboBox's Items
property and remove any drives that are not valid.

Hope this help.

{this code seems to work../}
procedure TMyDriveComboBox.Click;
var
        d: char;
  Item: Integer;
  drv: string;

  function DiskInDrive(Drive: Char): Boolean;
  var
    ErrorMode: word;
  begin
    {default result}
    Result := False;
    { make it upper case }
    if Drive in ['a'..'z'] then Dec(Drive, $20);
    { make sure it's a letter }
    if not (Drive in ['A'..'Z']) then
      raise EConvertError.Create('Not a valid drive ID');
    { turn off critical errors }
    ErrorMode := SetErrorMode(SEM_FailCriticalErrors);
    try
      { drive 1 = a, 2 = b, 3 = c, etc. }
      if DiskSize(Ord(Drive) - $40) <> -1 then Result := True;
    finally
      { restore old error mode }
      SetErrorMode(ErrorMode);
    end;
  end;

begin
  if ItemIndex >= 0 then begin
    d := UpCase(Items[ItemIndex][1]);
    if not DiskInDrive(d) then begin
      for Item := 0 to Items.Count - 1 do begin
        drv := Items[Item];
        if (UpCase(drv[1]) = UpCase(Drive)) and (drv[2] = ':') then begin
          ItemIndex := Item;
          break;
        end;
      end;
    end
    else Drive := d;
  end;
  inherited Click;
end;

-------------------------------------
Bill Florac: fl...@etcconnect.com
Fitco: http://sumac.etcconnect.com/~fitco/
-------------------------------------

Other Threads