Powershell 优化递归修改网络共享中文件ACL的脚本

Powershell 优化递归修改网络共享中文件ACL的脚本,powershell,Powershell,(你好!第一次在这里发帖,所以如果你觉得无聊,请不要对我太严厉:) 我有一项任务,我必须递归地对存储在文件共享上的根文件夹中的所有文件和文件夹设置“继承”,即从根文件夹复制ACL并将其应用于其所有子文件夹 这项任务因两个问题而变得复杂:第一,有些孩子没有所有者或不是Admins组;第二,有些文件的完整路径超过了256个符号的限制,因此无法通过常规方式处理(这两个问题都是在共享从一个NAS转移到另一个NAS之后出现的,而ROBOCOPY脚本显然不太理想) 这两个问题使我无法使用选中“使用此对象的可

(你好!第一次在这里发帖,所以如果你觉得无聊,请不要对我太严厉:)

我有一项任务,我必须递归地对存储在文件共享上的根文件夹中的所有文件和文件夹设置“继承”,即从根文件夹复制ACL并将其应用于其所有子文件夹

这项任务因两个问题而变得复杂:第一,有些孩子没有所有者或不是Admins组;第二,有些文件的完整路径超过了256个符号的限制,因此无法通过常规方式处理(这两个问题都是在共享从一个NAS转移到另一个NAS之后出现的,而ROBOCOPY脚本显然不太理想)

这两个问题使我无法使用选中“使用此对象的可继承权限替换所有子权限”选项的GUI,因为在某些时候(有时在处理数小时后),它会抛出“拒绝访问”错误,您必须跳过每个文件或完全取消该过程

为了避免这些问题,我编写了一个脚本来提升当前进程的权限(C#代码块无耻地从脚本中借用,只需稍加修改)并允许您将admin group设置为正在处理的文件/文件夹的所有者,从而允许您修改其ACL,同时使用DOS设备路径语法以相同的方式抓取和处理长名称的子项

换句话说,这个脚本正是我想要它做的。但它的速度非常慢,因为我们共享的每个文件夹都包含数十万个文件,每个文件在我脚本的进程块中的每次迭代中都会被单独处理。如果GUI对我有效的话,它的速度比GUI慢得多

所以我想也许一些关于StackOverflow的Powershell专家会建议一种方法来优化我那笨重的脚本&让它运行得更快?:)如果GUI能让它运行得更快,肯定有办法,对吧

$CSScriptBlock = @' advapi32.dll functions here that enable required privileges '@
function Adjust-Privilege { ... Add-Type $CSScriptBlock etc etc }

$root = "\\server\share\folder"

function restore-inheritance {
param(
[parameter(ValueFromPipelineByPropertyName=$True)]
[Alias('FullName')]
[string[]]$Path
)
    BEGIN ### enable privileges, get ACL from root folder
    { 
        "SeRestorePrivilege","SeBackupPrivilege","SeTakeOwnershipPrivilege" | Adjust-Privilege

        $acl = Get-ACL $root
        ### remove explicit ACEs
        $acl.Access | Where {$_.isinherited -eq $false} | % {
            $acl.RemoveAccessRule($_)
        }
    }

    PROCESS ### try to apply that ACL to children, set owner on failure and retry
    {   
        $DirOwner = New-Object System.Security.AccessControl.DirectorySecurity
        $DirOwner.SetOwner([System.Security.Principal.NTAccount]'Builtin\Administrators')
        $FileOwner = New-Object System.Security.AccessControl.FileSecurity
        $FileOwner.SetOwner([System.Security.Principal.NTAccount]'Builtin\Administrators')
         
        $path = $input.fullName    
        $litpath = "\\?\UNC" + $path.substring(1)

        if ([bool](get-item $path)) {
            try {
                Write-Host "Attempting to fix inheritance on [ $path ]"
                Set-Acl $path $acl -EA Stop
                }
            catch [System.Management.Automation.RuntimeException],`
                  [System.UnauthorizedAccessException],`
                  [System.IO.IOException] {
                Write-Host "Attempting to overwrite ownership of [ $path ]"
                $item = get-item $path
                if (!$item.PSIsContainer) {
                    $item.SetAccessControl($FileOwner)
                    Set-Acl $path $acl
                    }
                else {
                    $item.SetAccessControl($DirOwner)
                    Set-Acl $path $acl
                    }
                }
        }
        ### kicks in only when file is unreachable via regular path
        else {
            try {
                Write-Host "Attempting to fix inheritance on [ $litpath ]" -F Yellow
                Set-Acl -LiteralPath $litpath $acl -EA Stop
                }
            catch [System.Management.Automation.RuntimeException],`
                  [System.UnauthorizedAccessException],`
                  [System.IO.IOException] {
                Write-Host "Attempting to overwrite ownership of [ $litpath ]" -F Yellow
                $item = get-item -LiteralPath $litpath
                if (!$item.PSIsContainer) {
                    $item.SetAccessControl($FileOwner)
                    Set-Acl -LiteralPath $litpath $acl
                    }
                else {
                    $item.SetAccessControl($DirOwner)
                    Set-Acl -LiteralPath $litpath $acl
                    }
                }
            } 
    }

    END ### disable privileges
    {
        "SeRestorePrivilege","SeBackupPrivilege","SeTakeOwnershipPrivilege" | Adjust-Privilege -Disable
    }
}

get-childitem $root -Recurse -EA Stop | restore-inheritance


[1] win10有一个允许更长文件名的选项。在Windows 10中搜索
启用长文件名支持[2] 有一个stackexchange站点用于此>>>代码复查堆栈交换-我们被困在Win7上:(谢谢你的建议。arg!你可能需要使用代码审查网站来获取任何有用的信息。/////顺便说一句,我被教导说,一个人不应该利用股份的特权做任何事情……这应该是“所有人,所有事”。相反,应该尽可能使用底层文件系统并应用组priv…只有在需要时才应用用户priv&最好是通过继承,而不是通过“此项”。我想我会清除所有priv并用新的替换它们…如果可能,所有这些priv都是可继承的。[1]win10有一个允许更长文件名的选项。请在Windows 10中搜索
启用长文件名支持
。//有一个stackexchange站点用于此>>>代码复查堆栈交换-我们在Win7上遇到了麻烦:(谢谢你的建议。arg!你可能需要使用代码审查网站来获取任何有用的信息。/////顺便说一句,我被教导说,一个人不应该利用股份的特权做任何事情……这应该是“所有人,所有事”。相反,应该尽可能使用底层文件系统并应用组priv…只有在需要时才应用用户priv&最好是通过继承,而不是通过“this item”。我怀疑我会清除所有priv并将其替换为新的priv…如果可能,它们都是可继承的。