我试图让这个脚本工作,但我收到错误:
"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."
你知道出了什么问题吗?
非常感谢您的帮助。
有些事情需要修复,有些事情可以改进,所以我将它们分成几个部分:
您在主脚本中声明变量
$results
,但您试图在 Get-DirectoriesToDepth
函数内为其赋值。默认情况下,您的变量只能在 local 作用域 中访问,这意味着您尝试分配给第 42 行 $result
的值只能在该函数内部使用。这也意味着您的原始 $results
变量永远不会被分配任何值。您在这里应该做的是返回您找到的值,以便调用者范围可以访问该信息。有关详细信息,请参阅 Microsoft 关于 About_Scopes 的文章。
我发现您只想搜索到文件夹树中的某个点。
Get-ChildItem
已经有一个 -Depth
标志,指定您想要向下走多远,因此您的递归函数可以替换为 Get-ChildItem -Depth 2
。
运行
$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'."
希望有帮助!
问题:第一次使用
$results += [pscustomobject]@{ Path = $dir.FullName }
时,它会将 $Results
从数组转换为 [PSCustomObject]
。+=
失败了,因为它是一个别名方法。
解决方案:当您计划修改集合的内容(例如通过添加项目)时,不要使用数组,而是使用
List
。所以替换:
$results=@()
与 $results = [System.Collections.Generic.List[PSCustomObject]]::new()
$results += [pscustomobject]@{ Path = $dir.FullName }
与 $results.Add([pscustomobject]@{ Path = $dir.FullName })