如何使用Delphi测试目录是否可写?

时间:2010-08-30 09:38:13

标签: windows delphi permissions directory

目前我使用此函数,基于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 个答案:

答案 0 :(得分:18)

实际上,写入目录是确定目录是否可写的最简单方法。有太多的安全选项可供单独检查,即使这样你也可能会遗漏一些东西。

在调用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;

答案 1 :(得分:4)

以下是我使用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 :(得分:2)

...安德烈亚斯

使用安全API获取文件/目录的有效权限是PIA混乱而且不可靠。 (我倾倒了所有代码,只是为了检查我是否可以在目录中写一个文件。)

C.f。,http://www.ureader.com/msg/16591730.aspx

(我有其他参考,但我是新用户,只能发布一个链接。只需按照上面链接中给出的URL进行操作。)

答案 3 :(得分:0)

当然,您需要做的就是验证您对目录的访问权限。这有什么问题:

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;