如何检查写入目录或者文件的权限?
时间:2020-03-06 14:41:46 来源:igfitidea点击:
我有一个程序可以使用以下方法将一些数据写入文件。
public void ExportToFile(string filename)
{
using(FileStream fstream = new FileStream(filename,FileMode.Create))
using (TextWriter writer = new StreamWriter(fstream))
{
// try catch block for write permissions
writer.WriteLine(text);
}
}
运行程序时出现错误:
Unhandled Exception: System.UnauthorizedAccessException: Access to the path 'mypath' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access,
nt32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions
ptions, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access
FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolea
bFromProxy)
问题:我需要什么代码才能捕获此错误,如何授予访问权限?
解决方案
更新:
根据此答案修改了代码,以摆脱过时的方法。
我们可以使用Security名称空间进行检查:
public void ExportToFile(string filename)
{
var permissionSet = new PermissionSet(PermissionState.None);
var writePermission = new FileIOPermission(FileIOPermissionAccess.Write, filename);
permissionSet.AddPermission(writePermission);
if (permissionSet.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet))
{
using (FileStream fstream = new FileStream(filename, FileMode.Create))
using (TextWriter writer = new StreamWriter(fstream))
{
// try catch block for write permissions
writer.WriteLine("sometext");
}
}
else
{
//perform some recovery action here
}
}
就获得那些许可而言,我们将必须要求用户以某种方式为我们执行此操作。如果我们可以通过编程方式执行此操作,那么我们都会有麻烦;)
当代码执行以下操作时:
- 检查当前用户是否有权执行某项操作。
- 执行需要检入1的权利的操作。
我们冒着权限在1到2之间变化的风险,因为我们无法预测运行时系统上还会发生什么。因此,即使我们先前已经检查了权限,代码也应该处理引发UnauthorizedAccessException的情况。
请注意,SecurityManager类用于检查CAS权限,并且实际上不与OS一起检查当前用户是否对指定位置(通过ACL和ACE)具有写权限。因此,对于本地运行的应用程序,IsGranted将始终返回true。
示例(源自乔希的示例):
//1. Provide early notification that the user does not have permission to write.
FileIOPermission writePermission = new FileIOPermission(FileIOPermissionAccess.Write, filename);
if(!SecurityManager.IsGranted(writePermission))
{
//No permission.
//Either throw an exception so this can be handled by a calling function
//or inform the user that they do not have permission to write to the folder and return.
}
//2. Attempt the action but handle permission changes.
try
{
using (FileStream fstream = new FileStream(filename, FileMode.Create))
using (TextWriter writer = new StreamWriter(fstream))
{
writer.WriteLine("sometext");
}
}
catch (UnauthorizedAccessException ex)
{
//No permission.
//Either throw an exception so this can be handled by a calling function
//or inform the user that they do not have permission to write to the folder and return.
}
这很棘手,不建议尝试根据原始ACL(可通过System.Security.AccessControl类获得的所有ACL)以编程方式从文件夹中计算有效权限。有关Stack Overflow和更广泛的网络的其他答案,建议尝试执行该操作以了解是否允许权限。这篇文章总结了实现权限计算所需的知识,并且应该足以使我们摆脱此限制。
我们可以尝试使用以下代码块来检查目录是否具有写访问权限。
它检查FileSystemAccessRule。
string directoryPath = "C:\XYZ"; //folderBrowserDialog.SelectedPath;
bool isWriteAccess = false;
try
{
AuthorizationRuleCollection collection = Directory.GetAccessControl(directoryPath).GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
foreach (FileSystemAccessRule rule in collection)
{
if (rule.AccessControlType == AccessControlType.Allow)
{
isWriteAccess = true;
break;
}
}
}
catch (UnauthorizedAccessException ex)
{
isWriteAccess = false;
}
catch (Exception ex)
{
isWriteAccess = false;
}
if (!isWriteAccess)
{
//handle notifications
}
抱歉,以前的解决方案都没有帮助我。我需要检查双方:SecurityManager和SO权限。我已经通过Josh代码和iain答案学到了很多东西,但是恐怕我需要使用Rakesh代码(也感谢他)。仅有一个错误:我发现他只检查"允许"而不检查"拒绝"权限。所以我的建议是:
string folder;
AuthorizationRuleCollection rules;
try {
rules = Directory.GetAccessControl(folder)
.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
} catch(Exception ex) { //Posible UnauthorizedAccessException
throw new Exception("No permission", ex);
}
var rulesCast = rules.Cast<FileSystemAccessRule>();
if(rulesCast.Any(rule => rule.AccessControlType == AccessControlType.Deny)
|| !rulesCast.Any(rule => rule.AccessControlType == AccessControlType.Allow))
throw new Exception("No permission");
//Here I have permission, ole!

