PowerShell中文件夹ACL继承状态导出/导入失败问题求助
PowerShell导出/导入文件夹ACL继承状态失败问题
在使用Get-Acl、Set-Acl导出/导入文件夹的ACL继承状态时,导出的CSV内容显示正常,但执行导入脚本时报错,且文件夹的继承状态未被正确还原。
错误的导出代码
Get-ChildItem "k:\IT" -Recurse | ?{ $_.PsIsContainer } | %{ $Path = $_.FullName (Get-Acl $Path) | Select-Object ` @{n='Path';e={ $Path }}, AccessRightType, AccessRuleType, AuditRuleType, AreAccessRulesProtected, AreAuditRulesProtected, AreAccessRulesCanonical, AreAuditRulesCanonical } | Export-CSV "C:\acl\DirInhPermissions.csv"
错误的导入代码
$ruleset = Import-Csv -Path "C:\acl\DirInhPermissions.csv" foreach ( $i in $ruleset ) { $path=$i.Path $AccessRightType= $i.AccessRightType $AccessRuleType=$i.AccessRuleType $AuditRuleType= $i.AuditRuleType $AreAccessRulesProtected=$i.AreAccessRulesProtected $AreAuditRulesProtected=$i.AreAuditRulesProtected $AreAccessRulesCanonical=$i.AreAccessRulesCanonical $AreAuditRulesCanonical=$i.AreAuditRulesCanonical $acl = Get-Acl $path $permission = $AccessRightType,$AccessRuleType,$AuditRuleType,$AreAccessRulesProtected,$AreAuditRulesProtected,$AreAccessRulesCanonical,$AreAuditRulesCanonical $accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission $acl.SetAccessRule($accessRule) $acl | Set-Acl $path }
报错信息
执行导入脚本时出现如下错误:
new-object : 找不到接受实际参数"System.Security.AccessControl.FileSystemRights,System.Security.AccessControl.FileSystemAccessRule,System.Security.AccessControl.FileSystemAuditRule,False,False,True,True"的位置形式参数。
导出的CSV内容
#TYPE Selected.System.Security.AccessControl.DirectorySecurity "Path","AccessRightType","AccessRuleType","AuditRuleType","AreAccessRulesProtected","AreAuditRulesProtected","AreAccessRulesCanonical","AreAuditRulesCanonical" "K:\IT\New folder","System.Security.AccessControl.FileSystemRights","System.Security.AccessControl.FileSystemAccessRule","System.Security.AccessControl.FileSystemAuditRule","False","False","True","True" "K:\IT\New folder\xyz","System.Security.AccessControl.FileSystemRights","System.Security.AccessControl.FileSystemAccessRule","System.Security.AccessControl.FileSystemAuditRule","True","False","True","True" "K:\IT\New folder\xyz\123","System.Security.AccessControl.FileSystemRights","System.Security.AccessControl.FileSystemAccessRule","System.Security.AccessControl.FileSystemAuditRule","False","False","True","True"
对比:正常工作的单个访问权限导出/导入代码
导出代码
Get-ChildItem "k:\IT" -Recurse | ?{ $_.PsIsContainer } | %{ $Path = $_.FullName (Get-Acl $Path).Access | Select-Object ` @{n='Path';e={ $Path }}, IdentityReference, AccessControlType, InheritanceFlags, PropagationFlags, FileSystemRights } | Export-CSV "C:\acl\ACEPermissions.csv"
导入代码
$acerules = Import-Csv -Path "C:\acl\ACEPermissions.csv" foreach ( $i in $acerules ) { $path= $i.Path $IdentityReference= $i.IdentityReference $AccessControlType=$i.AccessControlType $InheritanceFlags= $i.InheritanceFlags $PropagationFlags=$i.PropagationFlags $FileSystemRights=$i.FileSystemRights $acl = Get-Acl $path $permission = $IdentityReference, $FileSystemRights, $InheritanceFlags, $PropagationFlags, $AccessControlType $accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission $acl.SetAccessRule($accessRule) $acl | Set-Acl $path }
问题根源与解决方案
问题分析
- 错误的对象操作逻辑:原导入脚本错误地将
DirectorySecurity对象的属性(AreAccessRulesProtected等)当作FileSystemAccessRule的构造参数,而这些属性属于ACL容器本身,不是单个访问规则的参数。 - 数据类型问题:CSV导出的布尔值是字符串格式("True"/"False"),直接使用无法被PowerShell识别为布尔类型。
- 冗余字段导出:
AccessRightType/AccessRuleType等类型字段对还原继承状态毫无作用,属于冗余导出内容。
修正后的导出代码
仅导出必要的路径和继承状态属性,无需冗余类型信息:
Get-ChildItem "k:\IT" -Recurse | Where-Object { $_.PsIsContainer } | ForEach-Object { $Path = $_.FullName $acl = Get-Acl $Path [PSCustomObject]@{ Path = $Path AreAccessRulesProtected = $acl.AreAccessRulesProtected AreAuditRulesProtected = $acl.AreAuditRulesProtected AreAccessRulesCanonical = $acl.AreAccessRulesCanonical AreAuditRulesCanonical = $acl.AreAuditRulesCanonical } } | Export-CSV "C:\acl\DirInhPermissions.csv" -NoTypeInformation
修正后的导入代码
直接操作DirectorySecurity对象的属性,通过对应的方法设置继承保护状态,并转换数据类型:
$ruleset = Import-Csv -Path "C:\acl\DirInhPermissions.csv" foreach ($i in $ruleset) { $path = $i.Path # 将CSV字符串转换为布尔类型 $areAccessProtected = [bool]::Parse($i.AreAccessRulesProtected) $areAuditProtected = [bool]::Parse($i.AreAuditRulesProtected) $areAccessCanonical = [bool]::Parse($i.AreAccessRulesCanonical) $areAuditCanonical = [bool]::Parse($i.AreAuditRulesCanonical) $acl = Get-Acl $path # 设置访问规则保护状态(第二个参数为是否保留已继承的规则) if ($areAccessProtected -ne $acl.AreAccessRulesProtected) { $acl.SetAccessRuleProtection($areAccessProtected, $true) } # 设置审计规则保护状态 if ($areAuditProtected -ne $acl.AreAuditRulesProtected) { $acl.SetAuditRuleProtection($areAuditProtected, $true) } # 规范化访问规则顺序(仅当需要时执行) if ($areAccessCanonical -and !$acl.AreAccessRulesCanonical) { $acl.Access | ForEach-Object { $acl.RemoveAccessRule($_) $acl.AddAccessRule($_) } } # 规范化审计规则顺序(仅当需要时执行) if ($areAuditCanonical -and !$acl.AreAuditRulesCanonical) { $acl.Audit | ForEach-Object { $acl.RemoveAuditRule($_) $acl.AddAuditRule($_) } } # 应用修改后的ACL $acl | Set-Acl $path }
内容的提问来源于stack exchange,提问作者RookieMistake
相关产品推荐
相关产品推荐

