C#Linq用于用户具有读取权限的文件
如何在C#Linq用于用户具有读取权限的文件,c#,linq,file-permissions,acl,C#,Linq,File Permissions,Acl,如何在list.Items=directoryInfo.GetFiles(“\\server\share\folder\”)上使用Linq是否仅包括用户具有读取权限的文件 。。。 到目前为止,只有建议使用try/catch,或者在.NET4.0中过时的API?我更喜欢阅读ACL,看看用户所属的特定用户或组是否已被授予读取权限。我尝试这样做是为了简化管理,在一个流量不高的网站上向用户授予报告,所以“谁知道当你试图打开文件时你是否真的可以阅读它”的逻辑不适用于这种情况。我觉得微软真的应该让这项任务变
list.Items=directoryInfo.GetFiles(“\\server\share\folder\”)上使用Linq
是否仅包括用户具有读取权限的文件
。。。
到目前为止,只有建议使用try/catch,或者在.NET4.0中过时的API?我更喜欢阅读ACL,看看用户所属的特定用户或组是否已被授予读取权限。我尝试这样做是为了简化管理,在一个流量不高的网站上向用户授予报告,所以“谁知道当你试图打开文件时你是否真的可以阅读它”的逻辑不适用于这种情况。我觉得微软真的应该让这项任务变得更容易。注意:我还没有测试过它,但理论上它应该可以工作 首先,定义一个谓词来确定读访问
bool CanRead(FileInfo file)
{
try {
file.GetAccessControl();
//Read and write access;
return true;
}
catch (UnauthorizedAccessException uae)
{
if (uae.Message.Contains("read-only"))
{
//read-only access
return true;
}
return false;
}
}
然后,应该是在linq查询中使用where子句的简单情况
from file in directoryInfo.GetFiles("\\server\share\folder\")
where HaveAccess(f) == true
select f;
试试这个。应该可以。不过还没有测试过
var fw = from f in new DirectoryInfo("C:\\Users\\User\\Downloads\\").GetFiles()
where SecurityManager.IsGranted(new FileIOPermission
(FileIOPermissionAccess.Write, f.FullName))
select f;
编辑如果只是只读文件,请尝试此操作
var fe = from f in new DirectoryInfo("C:\\Users\\ashley\\Downloads\\").GetFiles()
where f.IsReadOnly==true
select f
如果在打开文件之前检查读取权限,则可能会发生争用情况 如果您试图读取文件夹中您有权访问的所有文件,最好只打开每个文件并捕获
UnauthorizedAccessException
见:
void Main()
{
var directoryInfo = new DirectoryInfo(@"C:\");
var currentUser = WindowsIdentity.GetCurrent();
var files = directoryInfo.GetFiles(".").Where(f => CanRead(currentUser, f.FullName));
}
private bool CanRead(WindowsIdentity user, string filePath)
{
if(!File.Exists(filePath))
return false;
try
{
var fileSecurity = File.GetAccessControl(filePath, AccessControlSections.Access);
foreach(FileSystemAccessRule fsRule in fileSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)))
{
foreach(var usrGroup in user.Groups)
{
if(fsRule.IdentityReference.Value == usrGroup.Value)
return true;
}
}
} catch (InvalidOperationException) {
//File is in use
return false;
}
return false;
}
这是否适用于组内的组?显式拒绝权限怎么样?你可能可以。是的..但是在catch中声明一些逻辑听起来不是很简单。假设你有数千个文件,等待异常发生以获取其状态是非常昂贵的操作。@Ashley:那些try/catch我很确定是特例(驱动器不存在,或者您完全被锁定在文件夹之外)。您可以从Linq查询中调用该函数,这样您的高级代码仍然可以是漂亮的。它已经封装了true/false,所以您只需要将其插入
where
子句中。我不知道是否有更好的选项不使用p/Invoke(例如,Try
variant)。此外,我认为枚举文件系统上的文件可能已经是一个瓶颈。我推测,在这一点上,异常可以忽略不计。