windows 如何使用 Delphi 测试目录是否可写?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3599256/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I use Delphi to test if a Directory is writeable?
提问by mjn
Currently I use this function, based on JCL code, which works fine:
目前我使用这个函数,基于 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;
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?
有什么我可以改进的标志吗?可以在不实际创建文件的情况下完成测试吗?或者这个功能是否已经在 RTL 或 Jedi 库之一中可用?
回答by Remy Lebeau
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.
您还需要在调用之前关闭打开的句柄DeleteFile()
。由于您正在使用该FILE_FLAG_DELETE_ON_CLOSE
标志,因此您无论如何都不需要调用它。
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.
顺便说一句,您的代码中有一个小错误。您正在创建一个临时文件String
并将其分配给 a PWideChar
,但在实际使用String
之前超出范围,释放内存PWideChar
。您的FileName
变量应该是 aString
而不是 a PWideChar
。在调用时进行类型转换CreateFile()
,而不是之前。
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;
回答by kobik
Here is my version using GetTempFileName
which will attempt to create a uniquetemp file in the target directory:
这是我使用的版本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;
回答by Erik Knowles
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.)
使用安全 API 获取文件/目录的有效权限是 PIA 混乱,而且不可靠。(我为此转储了所有代码,以便仅检查是否可以在目录中写入文件。)
C.f., http://www.ureader.com/msg/16591730.aspx
参见,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.)
(我有其他参考资料,但我是新用户,只能发布一个链接。只需按照上面链接中给出的 URL 操作即可。)
回答by Norman Rorke
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;