Конференция "WinAPI" » Проверка существования папки [D7]
 
  • Виталий (17.01.16 13:33) [0]
    Доброе время суток. Долго думал куда поместить тему, решил сюда.

    В моей программе в файле настроек, кроме всего прочего есть путь к последней используемой папке.

    После чтения этого параметра, я проверяю, существует ли эта папка. Ее могли, например, удалить, тогда будет использована папка по умолчанию.

    Так вот, суть вопроса: сегодня возникла интересная ситуация. На одном компьютере использовалась папка e:\.....
    При переносе на другой компьютер обнаружилось: e - это cd и он не вставлен.
    Удивило поведение ф-и DirectoryExists - на ней программа просто упала (нет, не выкинула пользователю exception, а повисла напрочь).
    Собственно, вопрос, как скорректировать код в районе DirectoryExists(FolderName), чтобы она не висела при попытке проверить наличие папки на cd?
    Может как-то определить тип тома, заданного в FolderName предварительно или еще что... Думаю, в АПИ правильно тему поместил. сталкивался кто?
  • RWolf © (18.01.16 10:35) [1]

    > Может как-то определить тип тома,


    GetDriveType
  • Игорь Шевченко © (18.01.16 10:41) [2]
    Чего тут корректировать, я не понимаю:

    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;



    Функция отрабатывает мгновенно.
  • Игорь Шевченко © (18.01.16 10:42) [3]
    RWolf ©   (18.01.16 10:35) [1]

    http://www.gunsmoker.ru/2008/10/x-y-z.html
  • Виталий (18.01.16 12:30) [4]
    Хм. Ну может и к начинающим надо было )
    Зато я написал на "правильном" форуме и получил нужный ответ. В этой реализации DirectoryExists отрабатывает корректно и быстро. В том числе и для несуществующего CD.
    Кстати, Игорь, раз Вы меня поняли, то я все-таки написал "Я хочу получить X" )) Главное, Z не предлагать.
  • Игорь Шевченко © (18.01.16 12:59) [5]

    > Собственно, вопрос, как скорректировать код в районе DirectoryExists(FolderName),
    >  чтобы она не висела при попытке проверить наличие папки
    > на cd?
    > Может как-то определить тип тома, заданного в FolderName
    > предварительно или еще что...


    Возможно дело было не DirectoryExists...
  • Rouse_ © (18.01.16 19:07) [6]
    Я сталкивался с таким поведением, в частности описанное могут выдавать функции: 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:45) [7]
    Забыл дополнить, очень легко такое поведение воспроизвести на внешних кардридерах без вставленной флешки и на некоторых моделях внешних читателей флопи дисков.
  • Rouse_ © (18.01.16 19:48) [8]
    ЗЗЫ: иногда это можно увидеть наглядно - будет в фоне (не поверх всех окон) выведено сообщение мол диск не готов или что-то типа такого, я не помню как там точно сообщение выглядит.
  • Игорь Шевченко © (18.01.16 22:10) [9]
    Rouse_ ©   (18.01.16 19:07) [6]

    Да, есть такое дело, но программа не висит, а выдает сообщение, причем, забавное:
    ---------------------------
    Windows - Устройство не готово
    ---------------------------
    Exception Processing Message c00000a3 Parameters 75b3bf7c 4 75b3bf7c 75b3bf7c
    ---------------------------
    Отмена   Повторить   Продолжить  
    ---------------------------

    как вариант c0000013 на кард-ридере.

    Но окошко лечится через SetErrorMode(SEM_FAILCRITICALERRORS)
  • Rouse_ © (18.01.16 23:31) [10]
    О как, а вот про этот нюанс не знал - сеньк
  • Виталий (19.01.16 07:43) [11]
    Игорь, Rouse_, Спасибо, буду разбираться.
    Дело в том, что я вернул код на "как было", то есть встроенную DirectoryExists.
    Проверил (в данный момент на работе, соответственно другой компьютер) на "не вставленном сд) и... фантастика, он мгновенно выдал что нема папки, никаких зависаний.
    Я уж грешным делом подумал (после [5]), а не ситуация ли это "z не предлагать"...
    Похоже, вопрос требует дополнительной проработки, на тему, где конкретно возникает ошибка. Постараюсь в ближайшее время добраться до проблемной машинки и посмотреть что там все-таки получается.
  • Игорь Шевченко © (19.01.16 10:26) [12]
    Я приведу свой код для тестирования (так, на всякий случай)

    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

    {$R *.dfm}

    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.

 
Конференция "WinAPI" » Проверка существования папки [D7]
Есть новые Нет новых   [134427   +35][b:0][p:0.002]