Link to home
Start Free TrialLog in
Avatar of xpher
xpher

asked on

DriveComboBox & I/O Error 21

Using D4. How to stop I/O Error 21 when trying to access removeable media when no media present (i.e Floppy Drive - no disk, CD - No Disk, ZipDrive - No Disk). This is driving me mental. I have a project with the similar components and code that I worked on in D2. If I run the EXE from that old project I just get a message box saying Invalid filename.
Please help it's doin my ed in.

xpher.
Avatar of williams2
williams2

To do this there is a small part of the API making it possible to safetest a drive without having it to load anything. It described to stop the annoying "Please insert Disc in Driva A" dialog, but actually this is the only one I can't make working on my machine, and if it is a problem on my machine, it's possible that I'm not the only one.

BUT ..here's your answer (you should though test it on your floppy drive too, to see if I'm right):

function IsDriveReady(DriveLetter : char) : Boolean;
var  OldErrorMode : Word;
  OldDirectory : string;
  Error: Integer;
begin
  OldErrorMode := SetErrorMode(SEM_NOOPENFILEERRORBOX);
  {$I-}
  ChDir(DriveLetter + ':\');
  Error:= IoResult;
  Result:=  Error=0;
  {$I+}
  SetErrorMode(OldErrorMode);
end;


Regards,
Williams
Avatar of xpher

ASKER

Hi williams2
I've tried this with no great success. Also variable OldDirectory isn't used in your function. The line
GetDir(0, OldDirectory); should be placed in line after OldErrorMode :=

Thanks anyway

xpher
Try this:

function DriveReady(DriveLetter : char) : Boolean;
var
  Error: Integer;
begin
  {$I-}
  ChDir(DriveLetter + ':\');
  {$I+}
  Error:= IoResult;
  Result:=  Error = 0;
end;

This is how I have always done it, not sure why williams2 code didnt work, I think because it is checking IOResult before enabling IO checking again ($I+).  Also, I dont think you really need the SetErrorMode stuff, I never have needed it anyway.

Hope this helps
I just took it out of some code I have used some time ago and removed the unecessary stuff, but allright this one is tottally tested (Remeber to include "Uses Windows;" ):

function IsDriveReady(DriveLetter : char) : Boolean;
var
  OldErrorMode : Word;
begin
  OldErrorMode := SetErrorMode(SEM_NOOPENFILEERRORBOX);
  {$I-}
  ChDir(DriveLetter + ':\');
  Result:=  IoResult=0;
  {$I+}
  SetErrorMode(OldErrorMode);
end;

But you still won't find a solution for the A drive, besides Windows doesn't examine the floppy drive, so why would you?

This method is commonly known by WinAPI to do "Safe examinations", (You may try reading the FAQ at Inprise.com)

regards,
Williams
Avatar of xpher

ASKER

Heathprovost
Thanks but it is no more than I've tried already. If you would like to send me a sample of code of function in use with a DriveCombo I could check against my several attempts cluttering my hard drive.

To williams2
Regarding comment about windows not examining the floppy, it surely does if you try to access it even if no disk in drive?

Regards
Chris
ASKER CERTIFIED SOLUTION
Avatar of heathprovost
heathprovost
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
To heathprovost


"This is how I have always done it, not sure why williams2 code didnt work, I think because it is checking IOResult before enabling IO checking again ($I+)"

You ALWAYS have to go check the IOResult before enabling IO Check to avoid exceptions. Not all OS's accept this.

"Also, I dont think you really need the SetErrorMode stuff, I never have needed it anyway."

You don't think so? I guess you should go have a check at the Win32 API guide then. Not doing it sure makes a lot of mess running in Windows NT

To Chris:
I can only speak from my experience. The way I described it is ensured to stop ALL I/O requesters, but whether I check the IOResult or not I still get an error checking the A-drive, but weird enough only the A-drive.

And I can ensure you, that heathprovost's example will do at least the same.

Regards,
Williams
To Williams2

"You ALWAYS have to go check the IOResult before enabling IO Check to avoid exceptions. Not all OS's accept this"

I dont think that is correct. I may be wrong but at least Inprose agrees with me. Here is the example given in the Delphi 3 help file for IOResult

var

  F: file of Byte;
begin
  if OpenDialog1.Execute then begin
    AssignFile(F, OpenDialog1.FileName);
    {$I-}
    Reset(F);
    {$I+}
    if IOResult = 0 then
      MessageDlg('File size in bytes: ' + IntToStr(FileSize(F)),
        mtInformation, [mbOk], 0);
    else
      MessageDlg('File access error', mtWarning, [mbOk], 0);
  end;
end;

I aint arguing with you or anything, I was only guessing a reason as to why your code didnt work.  That was the only thing I found different than the Help files example.  If you are right they need to fix the damn help file :)

"You don't think so? I guess you should go have a check at the Win32 API guide then. Not doing it sure makes a lot of mess running in Windows NT"

I read the API and I would have to agree with you on this point. I suggest that xpher use Williams2 code to actually check the drive instead of mine, or at least implement his code which changes errormode.

Were is xpher anyway? I answered 3 hours ago and no response.

BTW williams2, do you agree with the reasoning in my answer? That should do it shouldnt it?
Yes heathprovost, I certainly do agree with your reasoning :-)

I know that Delphi writes this, but even though I have had experiences, that an error occured until I turned the IOResult checking inside the {$I+}, why? I don't know.

but I sure have had my problems with this thing as I am building a remote file access system. Some OS installations does accept silent checking of drives when disabling IOChecking, while I have had experiences that NT Server + Workstation doesn't.

But the question was regarding the file combobox, why I don't see why he should accept my answer prior to yours, so I don't have a problem with that :-) . I was just making a point that some OS's accept this, and some don't

Regards,
Williams
Avatar of xpher

ASKER

Apologies for delay in replying but haven't had a lot of time. Also wanted to try out all possibilities from your comments etc.
Williams2
Hate rejecting anybody but at the end of the day the last answer from heathprovost got to the root of problem. (Although I did slip a message in there to give info to user).
Heathprovost
Thanks the last one clinched it.

Regards
Xpher
Ok, everybody. I know this is a little late, but I just think you should know, that I found a generel solution to the problem, even BAD errors won't generate any alarm:

function IsDriveReady(DriveLetter : char): Boolean;
var
  DrvNum: byte;
  EMode: Word;
begin
  result := false;
  DrvNum := ord(DriveLetter);
  if DrvNum >= ord('a') then dec(DrvNum,$20);
  EMode := SetErrorMode(SEM_FAILCRITICALERRORS);
  try
    if DiskSize(DrvNum-$40) <> -1 then result := true;
  finally
    SetErrorMode(EMode);
  end;
end;

I just wanted you to know, because this one works with all drives I know.

Regards,
Williams