Solved

DriveComboBox & I/O Error 21

Posted on 1999-01-04
11
796 Views
Last Modified: 2010-04-04
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.
0
Comment
Question by:xpher
  • 5
  • 3
  • 3
11 Comments
 
LVL 3

Expert Comment

by:williams2
Comment Utility
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
0
 
LVL 1

Author Comment

by:xpher
Comment Utility
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
0
 
LVL 5

Expert Comment

by:heathprovost
Comment Utility
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
0
 
LVL 3

Expert Comment

by:williams2
Comment Utility
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
0
 
LVL 1

Author Comment

by:xpher
Comment Utility
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
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 5

Accepted Solution

by:
heathprovost earned 50 total points
Comment Utility
VERY INTERESTING!!!  I think I got it though.  I didnt realize exactly what you were doing.  The actual problem is not with the DriveComboBox, But with the DirectoryListBox attached to it. It does NOT check drive for readiness, and there is no way to fix it short of modifying the original delphi source code (DriveChange method is private :( ).  The easiest thing to do is not to attach the ListBox to it, and then add the following to the DriveComboBox change event:

procedure TForm1.DriveComboBox1Change(Sender: TObject);
begin
  if DriveReady(DriveComboBox1.Drive) then //test if drive ready
        DirectoryListBox1.Drive := DriveComboBox1.Drive //set if ready
  else
    DriveComboBox1.Drive := 'C'; //reset to known good drive
end;

Just use the DriveReady code I posted earilier to test
Hope this helps
0
 
LVL 3

Expert Comment

by:williams2
Comment Utility
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
0
 
LVL 5

Expert Comment

by:heathprovost
Comment Utility
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?
0
 
LVL 3

Expert Comment

by:williams2
Comment Utility
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
0
 
LVL 1

Author Comment

by:xpher
Comment Utility
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
0
 
LVL 3

Expert Comment

by:williams2
Comment Utility
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
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now