目前我使用此函数,基于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库中提供了吗?
答案 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;