PowerShell -> 仅具有 NTFS 组权限的目录。错误

问题描述 投票:0回答:2

我试图让这个脚本工作,但我收到错误:

"Method invocation failed because [System.Management.Automation.PSObject] doesn't contain a method named 'op_Addition'."

此脚本应仅将仅具有 AD 组的目录导出为 NTFS 权限(没有 AD 帐户 - S-1-5-21)。

# Basispfad, unter dem die Verzeichnisse durchsucht werden sollen
$basePath = "C:\PfadZuIhremVerzeichnis"

# Pfad und Dateiname der CSV-Datei
$csvExportPath = "C:\PfadZumSpeichern\DirectoriesWithGroupOnlyPermissions.csv"

# Sammelt Informationen über Verzeichnisse
$results = @()

# Funktion, die überprüft, ob nur Gruppenberechtigungen vorhanden sind
function HasOnlyGroupPermissions {
    param ([string]$path)

    $acl = Get-Acl -Path $path
    foreach ($access in $acl.Access) {
        if (-not $access.IsInherited -and ($access.IdentityReference.ToString() -notmatch '^S-1-5-21.*\\[^\\]+$')) {
            # Es handelt sich um eine direkte Berechtigung, die nicht einer Gruppe zugeordnet ist.
            return $false
        }
    }
    return $true
}

# Funktion, um nur Verzeichnisse bis zur gewünschten Tiefe zu erfassen
function Get-DirectoriesToDepth {
    param (
        [string]$rootPath,
        [int]$maxDepth,
        [int]$currentDepth = 0
    )

    # Basisfall: Wenn maximale Tiefe erreicht ist, stoppe die Rekursion
    if ($currentDepth -ge $maxDepth) {
        return
    }

    # Verzeichnisse auf der aktuellen Ebene finden
    $childDirs = Get-ChildItem -Path $rootPath -Directory -ErrorAction SilentlyContinue
    foreach ($dir in $childDirs) {
        # Aktuelles Verzeichnis hinzufügen
        if (HasOnlyGroupPermissions -path $dir.FullName) {
            $results += [pscustomobject]@{
                Path = $dir.FullName
            }
        }
        # Rekursiver Aufruf für die nächste Ebene
        Get-DirectoriesToDepth -rootPath $dir.FullName -maxDepth $maxDepth -currentDepth ($currentDepth + 1)
    }
}

# Start der Suche
Get-DirectoriesToDepth -rootPath $basePath -maxDepth 2

# Ergebnisse in CSV exportieren
$results | Export-Csv -Path $csvExportPath -NoTypeInformation -Encoding UTF8

Write-Host "Die Verzeichnisse mit ausschließlich Gruppenberechtigungen bis zu einer Tiefe von 2 Ebenen wurden nach '$csvExportPath' exportiert."

你知道出了什么问题吗?

非常感谢您的帮助。

powershell ntfs
2个回答
0
投票

有些事情需要修复,有些事情可以改进,所以我将它们分成几个部分:

范围

您在主脚本中声明变量

$results
,但您试图在
Get-DirectoriesToDepth
函数内为其赋值。默认情况下,您的变量只能在 local 作用域 中访问,这意味着您尝试分配给第 42 行
$result
的值只能在该函数内部使用。这也意味着您的原始
$results
变量永远不会被分配任何值。您在这里应该做的是返回您找到的值,以便调用者范围可以访问该信息。有关详细信息,请参阅 Microsoft 关于 About_Scopes 的文章

使用 -Depth 标志获取-ChildItem

我发现您只想搜索到文件夹树中的某个点。

Get-ChildItem
已经有一个
-Depth
标志,指定您想要向下走多远,因此您的递归函数可以替换为
Get-ChildItem -Depth 2

访问规则、字符串翻译和 Get-ADObject

运行

$Access.IdentityReference.ToString()
将始终以
DOMAIN\ACCOUNT
格式返回用户帐户。这意味着现有用户将按原样返回,并且您的脚本仅在发现AD 中不再存在的用户时才会停止。如果您确实只想查看组,那么您还需要排除现有用户。要查找 AD 对象是用户还是组,您可以运行
Get-ADObject
并查看
ObjectClass
属性:

$AccountNameWithoutDomain = $( $( $Access.IdentityReference.Value -split "\\" )[1] )
Get-ADObject -Filter "SamAccountName -eq '$AccountNameWithoutDomain'"

此示例通过引用

$Access
.Value
来使用您的
IdentityReference
变量,并用反斜杠将其分割以仅使用帐户名称。然后它获取具有该名称的 AD 对象。返回值将如下所示:

DistinguishedName                          Name      ObjectClass ObjectGUID                          
-----------------                          ----      ----------- ----------                          
CN=My User,CN=Users,DC=myad,DC=local       My User   user        ....

如果

ObjectClass
是“
Group
”,那么您就知道这是一个组。请注意,如果该对象不存在,
Get-ADObject
将返回
$null
,在这种情况下,我们可以得出结论,它将是本地帐户(
NT AUTHORITY\SYSTEM
CREATOR OWNER
等),除非您正在运行大量具有混合组的多域环境。

把它们放在一起

因此,您想要的是列出特定深度的所有文件夹,并且仅列出权限仅具有域组的文件夹。这是带有附加错误处理的完整代码。

# Basispfad, unter dem die Verzeichnisse durchsucht werden sollen
$basePath = "C:\PfadZuIhremVerzeichnis"

# Pfad und Dateiname der CSV-Datei
$csvExportPath = "C:\PfadZumSpeichern\DirectoriesWithGroupOnlyPermissions.csv"
$csvExportPathErrors = "C:\PfadZumSpeichern\DirectoriesWithGroupOnlyPermissions - Errors.csv"

# Sammelt Informationen über Verzeichnisse
$results = @()
$FailedToReadAcl = @()
$MaxDepth = 2

$AllFolders = Get-ChildItem -Path $basePath -Depth $MaxDepth -Directory -ErrorAction SilentlyContinue

:FolderLoop foreach ($Folder in $AllFolders) {
    
    #This section stores all failed Get-Acl attempts to a separate variable (access denied etc.)
    try {
        $Acl = Get-Acl -Path $Folder.FullName -ErrorAction SilentlyContinue    
    }
    catch {
        $FailedToReadAcl += $Folder.FullName
        continue
    }

    #Loop through all access rules for the folder
    $AddFolder = $true
    :AccessLoop foreach ($AccessRule in $Acl.Access) {
        $UsernameWithoutDomain = ($AccessRule.IdentityReference.Value -split "\\")[1]

        #NT AUTHORITY\SYSTEM permissions can sometimes cause the Get-ADObject to fail, so this breaks the loop before that happens.
        if ($UsernameWithoutDomain -eq "SYSTEM") {
            break AccessLoop
        }

        #If the object is NOT a security group, break the loop
        $ADObject = Get-ADObject -Filter "SamAccountName -eq '$UsernameWithoutDomain'"
        if ([string]::IsNullOrEmpty($ADObject) -or $ADObject.ObjectClass -ne "group") {
            $AddFolder = $false
            break AccessLoop
        }
    }

    if ($AddFolder) {
        $results += [pscustomobject]@{
            Path = $Folder.FullName
        }
    }
}

# Ergebnisse in CSV exportieren
$results | Export-Csv -Path $csvExportPath -NoTypeInformation -Encoding UTF8
$FailedToReadAcl | Export-Csv -Path $csvExportPathErrors -NoTypeInformation -Encoding UTF8

Write-Host "Die Verzeichnisse mit ausschließlich Gruppenberechtigungen bis zu einer Tiefe von 2 Ebenen wurden nach '$csvExportPath' exportiert."
Write-Host "All inaccessible folders were exported to the CSV file '$csvExportPathErrors'."

希望有帮助!


0
投票

问题:第一次使用

 $results += [pscustomobject]@{ Path = $dir.FullName }
时,它会将
$Results
从数组转换为
[PSCustomObject]

因此
+=
失败了,因为它是一个别名方法。

解决方案:当您计划修改集合的内容(例如通过添加项目)时,不要使用数组,而是使用

List

(注意:List 也优于 ArrayList)

所以替换:

  • $results=@()
    $results = [System.Collections.Generic.List[PSCustomObject]]::new()
  •  $results += [pscustomobject]@{ Path = $dir.FullName }
    $results.Add([pscustomobject]@{ Path = $dir.FullName })
© www.soinside.com 2019 - 2024. All rights reserved.