PowerShell调用SetAccessRule/AddAccessRule报PSMethod错误如何解决?
错误根因与修复方案
核心报错原因
你遇到的报错直接来源于语法错误:SetAccessRule是ACL对象的方法,不是可赋值的属性,你代码中写的$foldacl.SetAccessRule=($Ar)属于尝试给方法对象赋值,自然触发Cannot set the Value property for PSMemberInfo object的错误。
除此之外你的代码还有多处会导致运行异常或逻辑不符合预期的问题:
- 直接从
$foldacl.Access集合取InheritanceFlags/PropagationFlags等属性,拿到的是所有权限条目的属性数组,传入单个规则的构造函数会出现参数不匹配 - 没有移除旧的
WORKGROUP前缀的权限条目,执行后会出现新旧两条权限同时存在的问题,达不到替换的效果 - 未判断身份名称是否包含
\,遇到无域前缀的内置身份时,IndexOf("\")返回-1会触发子字符串截取报错 Get-ChildItem没有限制仅获取文件夹,拿到的文件对象也会被处理,会出现不必要的错误
修正后可正常运行的脚本
# 仅获取目标路径下的所有文件夹 $folders = Get-ChildItem -Path "C:\Users\spewingadmin\Documents\reports_bak2\" -Recurse -Directory foreach($folder in $folders){ $foldacl = Get-Acl -Path $folder.FullName # 遍历当前文件夹的所有ACL权限条目 for ($x=0; $x -lt $foldacl.Access.Count; $x++){ $accessRule = $foldacl.Access[$x] $user = $accessRule.IdentityReference # 先判断身份是否包含域前缀分隔符\,避免截取报错 $backslashPos = $user.Value.IndexOf("\") if($backslashPos -le 0){ continue } $domainresult = $user.Value.Substring(0, $backslashPos) # 仅处理WORKGROUP前缀的身份 if($domainresult -eq "WORKGROUP") { # 提取用户名,拼接新域前缀 $username = $user.Value.Substring($backslashPos + 1) $DomainUser = "NEWWORKGROUP\" + $username # 从当前旧规则中获取对应权限参数 $InheritanceFlag = $accessRule.InheritanceFlags $PropagationFlag = $accessRule.PropagationFlags $objType = $accessRule.AccessControlType $Permissions = $accessRule.FileSystemRights # 构造新的权限规则 $NewPerms = ($DomainUser, $Permissions, $InheritanceFlag, $PropagationFlag, $objType) $Ar = New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList $NewPerms # 先移除旧的权限规则,再添加新规则 $foldacl.RemoveAccessRule($accessRule) | Out-Null $foldacl.SetAccessRule($Ar) } } # 将修改后的ACL写回文件夹 Set-Acl -Path $folder.FullName -AclObject $foldacl }
关键修正说明
- 把错误的属性赋值写法
$foldacl.SetAccessRule=($Ar)改为正确的方法调用写法$foldacl.SetAccessRule($Ar),同时增加了旧规则移除逻辑,实现真正的权限替换 - 所有权限参数都从当前遍历的单条权限规则
$foldacl.Access[$x]中获取,保证参数和权限规则一一对应 - 增加了分隔符存在性判断、仅处理文件夹的逻辑,避免边界场景报错
- 放开了
Set-Acl的注释,修改后的ACL会实际生效,测试时可以先注释该行确认输出符合预期再开启
内容的提问来源于stack exchange,提问作者Sean Ewing
相关产品推荐
相关产品推荐

