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.
Please help it's doin my ed in.
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
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
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_NOOPENFIL EERRORBOX) ;
{$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
function IsDriveReady(DriveLetter : char) : Boolean;
var
OldErrorMode : Word;
begin
OldErrorMode := SetErrorMode(SEM_NOOPENFIL
{$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
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
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
"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?
"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
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
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
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_FAILCRITI CALERRORS) ;
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
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_FAILCRITI
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
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_NOOPENFIL
{$I-}
ChDir(DriveLetter + ':\');
Error:= IoResult;
Result:= Error=0;
{$I+}
SetErrorMode(OldErrorMode)
end;
Regards,
Williams