如果目标文件夹的大小非常大,使用System.Security.AccessControl从文件夹中删除ACE的速度非常

本文关键字:非常 文件夹 删除 速度 AccessControl ACE 使用 小非 目标 如果 System | 更新日期: 2023-09-27 18:03:10

我需要删除某些帐户(如"Everyone"从共享的特定子文件夹上的ACL中获取。我获得一个DirectorySecurity对象,获取并循环AuthorizationRuleCollection,从ACL中删除有问题的AccessRule,然后调用SetAccessControl来应用更改。如果目标文件夹很小,一切都可以正常工作,但是如果它有很多子文件夹和文件,则可能需要很长时间才能应用更改(比手动操作要长得多)。我只想处理目标文件夹上的ACL。有办法做到这一点使用。net DirectorySecurity类吗?或者我必须求助于Win32 API或其他解决方案吗?

下面是一段代码。当文件夹大小非常大时,调用dirInfo.SetAccessControl(dirSec)是挂起的地方。

DirectoryInfo dirInfo = new DirectoryInfo(path);
DirectorySecurity dirSec = dirInfo.GetAccessControl();
AuthorizationRuleCollection acl = dirSec.GetAccessRules(true, true,     
                                  typeof(System.Security.Principal.NTAccount));
foreach (FileSystemAccessRule ace in acl)
{
    if (groupsToRemove.Contains(ace.IdentityReference.Value))
    {
        dirSec.RemoveAccessRuleSpecific(ace);
        dirInfo.SetAccessControl(dirSec);
    }
}

如果目标文件夹的大小非常大,使用System.Security.AccessControl从文件夹中删除ACE的速度非常

DirectoryInfo dirInfo = new DirectoryInfo(path);
DirectorySecurity dirSec = dirInfo.GetAccessControl();
AuthorizationRuleCollection acl = dirSec.GetAccessRules(true, true,     
                                  typeof(System.Security.Principal.NTAccount));
foreach (FileSystemAccessRule ace in acl)
{
    if (groupsToRemove.Contains(ace.IdentityReference.Value))
    {
        dirSec.RemoveAccessRuleSpecific(ace);
        dirInfo.SetAccessControl(dirSec);
    }
}

在你的代码中,你在每次循环的迭代中都对ACL应用更新,这变得非常昂贵。你试过将dirInfo.SetAccessControl(dirSec);移出foreach吗?这应该调用一次DirectoryInfo对象上的SetAccessControl方法,一次应用所有更改,如下所示:

foreach (FileSystemAccessRule ace in acl)
{
    if (groupsToRemove.Contains(ace.IdentityReference.Value))
    {
        dirSec.RemoveAccessRuleSpecific(ace);        
    }
}
dirInfo.SetAccessControl(dirSec);

必须设置SE_DACL_PROTECTED标志,以"防止在父容器的DACL上设置的ace,以及目录层次结构中位于父容器之上的任何对象被应用于对象DACL"。这可能会加快操作速度,因为它不必应用所有子对象。同样来自MSDN,

请注意,SE_DACL_PRESENT标志必须存在才能进行设置SE_DACL_PROTECTED和SE_SACL_PRESENT必须存在才能设置SE_SACL_PROTECTED .

然后必须使用IADsSecurityDescriptor。控件属性来控制对象是否从其父容器继承acl和sacl。

更多信息可在MSDN上获得。