Как я могу использовать Delphi, чтобы проверить, доступен ли каталог для записи? - PullRequest
9 голосов
/ 30 августа 2010

В настоящее время я использую эту функцию, основанную на коде JCL, которая отлично работает:

function IsDirectoryWriteable(const AName: string): Boolean;
var
  FileName: PWideChar;
  H: THandle;
begin
  FileName := PWideChar(IncludeTrailingPathDelimiter(AName) + 'chk.tmp');

  H := CreateFile(FileName, GENERIC_READ or GENERIC_WRITE, 0, nil,
    CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY or FILE_FLAG_DELETE_ON_CLOSE, 0);

  Result := H <> INVALID_HANDLE_VALUE;

  DeleteFile(FileName);
end;

Можно ли что-нибудь улучшить с помощью флагов? Может ли тест быть выполнен без фактического создания файла? Или эта функция уже доступна в одной из библиотек RTL или Jedi?

Ответы [ 4 ]

19 голосов
/ 31 августа 2010

На самом деле запись в каталог - это самый простой способ определить, доступен ли каталог для записи.Слишком много вариантов безопасности доступно для индивидуальной проверки, и даже в этом случае вы можете что-то пропустить.

Вам также необходимо закрыть открытый дескриптор перед вызовом DeleteFile().В любом случае вам не нужно звонить, поскольку вы используете флаг FILE_FLAG_DELETE_ON_CLOSE.

Кстати, в вашем коде есть небольшая ошибка.Вы создаете временный String и присваиваете ему PWideChar, но String выходит из области видимости, освобождая память, до фактического использования PWideChar.Ваша переменная FileName должна быть String вместо PWideChar.Выполните приведение типа при вызове CreateFile(), не раньше.

Попробуйте это:

function IsDirectoryWriteable(const AName: string): Boolean; 
var 
  FileName: String; 
  H: THandle; 
begin 
  FileName := IncludeTrailingPathDelimiter(AName) + 'chk.tmp'; 
  H := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil, 
    CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY or FILE_FLAG_DELETE_ON_CLOSE, 0); 
  Result := H <> INVALID_HANDLE_VALUE; 
  if Result then CloseHandle(H);
end;
4 голосов
/ 07 сентября 2017

Вот моя версия, использующая GetTempFileName, которая будет пытаться создать уникальный временный файл в целевой папке:

function IsDirecoryWriteable(const AName: string): Boolean;
var
  TempFileName: array[0..MAX_PATH] of Char;
begin
  { attempt to create a temp file in the directory }
  Result := GetTempFileName(PChar(AName), '$', 0, TempFileName) <> 0;
  if Result then
    { clean up }
    Result := DeleteFile(TempFileName);
end;
2 голосов
/ 30 августа 2010

Андреас ...

Использование API безопасности для получения эффективных прав на файл / каталог - беспорядок в PIA и просто ненадежный.(Я выкинул весь свой код для этого, чтобы просто проверить, могу ли я записать файл в директорию.)есть другие ссылки, но я новый пользователь и могу опубликовать только одну ссылку. Просто следуйте вместе с URL-адресами, указанными в ссылке выше.)

0 голосов
/ 12 июля 2017

Конечно, все, что вам нужно сделать, это подтвердить свои права доступа к Справочнику. Что не так с этим:

function IsDirectoryWriteable(aName : String);
var
  FileObject : TJwSecureFileObject;
  DesiredAccess: ACCESS_MASK;
begin
  DesiredAccess := FILE_GENERIC_WRITE;
  FileObject := TJwSecureFileObject.Create(aName);
  try
    result := FileObject.AccessCheck(DesiredAccess);
  finally
    FileObject.Free;
  end;
end;
...