-
Доброе время суток. Долго думал куда поместить тему, решил сюда.
В моей программе в файле настроек, кроме всего прочего есть путь к последней используемой папке.
После чтения этого параметра, я проверяю, существует ли эта папка. Ее могли, например, удалить, тогда будет использована папка по умолчанию.
Так вот, суть вопроса: сегодня возникла интересная ситуация. На одном компьютере использовалась папка e:\..... При переносе на другой компьютер обнаружилось: e - это cd и он не вставлен. Удивило поведение ф-и DirectoryExists - на ней программа просто упала (нет, не выкинула пользователю exception, а повисла напрочь). Собственно, вопрос, как скорректировать код в районе DirectoryExists(FolderName), чтобы она не висела при попытке проверить наличие папки на cd? Может как-то определить тип тома, заданного в FolderName предварительно или еще что... Думаю, в АПИ правильно тему поместил. сталкивался кто?
-
> Может как-то определить тип тома,
GetDriveType
-
Чего тут корректировать, я не понимаю: function DirectoryExists(const Directory: string): Boolean;
var
Code: Cardinal;
begin
Code := GetFileAttributes(PChar(Directory));
Result := (Code <> INVALID_FILE_ATTRIBUTES) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
end; Функция отрабатывает мгновенно.
-
-
Хм. Ну может и к начинающим надо было ) Зато я написал на "правильном" форуме и получил нужный ответ. В этой реализации DirectoryExists отрабатывает корректно и быстро. В том числе и для несуществующего CD. Кстати, Игорь, раз Вы меня поняли, то я все-таки написал "Я хочу получить X" )) Главное, Z не предлагать.
-
> Собственно, вопрос, как скорректировать код в районе DirectoryExists(FolderName), > чтобы она не висела при попытке проверить наличие папки > на cd? > Может как-то определить тип тома, заданного в FolderName > предварительно или еще что...
Возможно дело было не DirectoryExists...
-
Я сталкивался с таким поведением, в частности описанное могут выдавать функции: GetFileAttributes и GetDiskFreeSpaceEx. Решается простой проверкой:
var SN, A, B: DWORD; // можно в данном случае и не инициализировать begin if not GetVolumeInformation(PChar(Disk), nil, 0, @SN, A, B, nil, 0) then Exit;
Если GetVolumeInformation вернет False, то GetFileAttributes (с условием что мы к диску обращаемся) нет смысла дергать.
-
Забыл дополнить, очень легко такое поведение воспроизвести на внешних кардридерах без вставленной флешки и на некоторых моделях внешних читателей флопи дисков.
-
ЗЗЫ: иногда это можно увидеть наглядно - будет в фоне (не поверх всех окон) выведено сообщение мол диск не готов или что-то типа такого, я не помню как там точно сообщение выглядит.
-
Rouse_ © (18.01.16 19:07) [6]
Да, есть такое дело, но программа не висит, а выдает сообщение, причем, забавное: --------------------------- Windows - Устройство не готово --------------------------- Exception Processing Message c00000a3 Parameters 75b3bf7c 4 75b3bf7c 75b3bf7c --------------------------- Отмена Повторить Продолжить ---------------------------
как вариант c0000013 на кард-ридере.
Но окошко лечится через SetErrorMode(SEM_FAILCRITICALERRORS)
-
О как, а вот про этот нюанс не знал - сеньк
-
Игорь, Rouse_, Спасибо, буду разбираться. Дело в том, что я вернул код на "как было", то есть встроенную DirectoryExists. Проверил (в данный момент на работе, соответственно другой компьютер) на "не вставленном сд) и... фантастика, он мгновенно выдал что нема папки, никаких зависаний. Я уж грешным делом подумал (после [5]), а не ситуация ли это "z не предлагать"... Похоже, вопрос требует дополнительной проработки, на тему, где конкретно возникает ошибка. Постараюсь в ближайшее время добраться до проблемной машинки и посмотреть что там все-таки получается.
-
Я приведу свой код для тестирования (так, на всякий случай) unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm2 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
procedure CheckDirectory(const ADirName: string);
end;
var
Form2: TForm2;
implementation
procedure TForm2.Button1Click(Sender: TObject);
const DirName: string = ':\FooBar';
var
C: Char;
begin
Memo1.Lines.Clear;
for C in ['A'..'Z'] do
CheckDirectory(C + DirName);
end;
procedure TForm2.CheckDirectory(const ADirName: string);
var
OldErrorMode: DWORD;
begin
OldErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS);
try
if DirectoryExists(ADirName) then
Memo1.Lines.Add(Format('%s exists', [ADirName]))
else
Memo1.Lines.Add(Format('%s does not exist', [ADirName]));
finally
SetErrorMode(OldErrorMode);
end;
end;
end.
|