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

mjn*_*mjn 10 windows delphi directory permissions

目前我使用这个函数,基于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;
Run Code Online (Sandbox Code Playgroud)

我可以用旗帜改进吗?可以在不实际创建文件的情况下完成测试吗?或者这个功能甚至已经在其中一个RTL或Jedi库中提供了?

Rem*_*eau 20

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

您还需要在调用DeleteFile()之前关闭打开的句柄.因为您使用DeleteFile()旗帜,所以无论如何都不需要这样做.

顺便说一句,你的代码中有一个小错误.您正在创建一个临时String并将其分配给PWideChar,但在实际使用PWideChar之前,String超出范围,释放内存.您的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;
Run Code Online (Sandbox Code Playgroud)

  • 临时字符串不会超出范围.临时范围与函数中的其他内容相同.它仅在函数退出时被破坏,或者当临时需要重新用于保存另一个临时字符串时才会被销毁. (2认同)
  • 但是你必须使用"随机"文件名,因为如果文件chk.tmp已经存在于checked目录中,则函数返回FALSE. (2认同)

kob*_*bik 5

这是我使用的版本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;
Run Code Online (Sandbox Code Playgroud)