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

发布于 2024-09-16 05:19:45 字数 537 浏览 1 评论 0原文

目前我使用这个基于 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 库之一中可用?

Currently I use this function, based on JCL code, which works fine:

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;

Is there anything I could improve with the flags?
Can the test be done without actually creating a file?
Or is this functionality even already available in one of the RTL or Jedi libraries?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

匿名。 2024-09-23 05:19:45

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

您还需要在调用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;

Actually writing to the directory is the simpliest way to determine if the directory is writable. There are too many security options available to check individually, and even then you might miss something.

You also need to close the opened handle before calling DeleteFile(). Which you do not need to call anyway since you are using the FILE_FLAG_DELETE_ON_CLOSE flag.

BTW, there is a small bug in your code. You are creating a temporary String and assigning it to a PWideChar, but the String goes out of scope, freeing the memory, before the PWideChar is actually used. Your FileName variable should be a String instead of a PWideChar. Do the type-cast when calling CreateFile(), not before.

Try this:

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;
黯然#的苍凉 2024-09-23 05:19:45

这是我使用 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;

Here is my version using GetTempFileName which will attempt to create a unique temp file in the target directory:

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;
夜司空 2024-09-23 05:19:45

Andreas...

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

Cf,http://www.ureader.com/msg/16591730.aspx

(我还有其他参考资料,但我是新用户,只能发布一个链接。只需关注以及上面链接中给出的 URL。)

Andreas...

Using the security APIs to get the effective rights for a file/directory is a PIA mess and just not reliable. (I dumped all of my code for doing so in favor of just checking to see if I could write a file in the dir.)

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

(I have other refs., but I'm a new user and can post only one link. Just follow along with the URLS given in the link above.)

不知在何时 2024-09-23 05:19:45

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

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;

Surely all you need to do is verify your Access Rights to the Directory. What is wrong with this:

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文