Отчет ADSI в PowerShell - Рекурсивные группы

У меня есть этот код в PowerShell, который просматривает группы и пользователей и создает файл txt с разделителями табуляции с полями, которые я хочу.

Однако он находит только половину информации. Я пытаюсь заменить другой процесс, который генерирует идентичный отчет, и этот отчет собирает около 580 000 строк данных, где, поскольку этот отчет PowerShell генерирует всего около 300 000. Мне кажется, мне нужно рекурсивно смотреть в группы, но я не уверен, как это сделать.

код:

#requires -version 2

$ScriptName = $************.MyCommand.Name
$ADS_GROUP_TYPE_SECURITY_ENABLED = 0x80000000
$PageSize = 250 # Adjust as needed

# Create the Pathname object and enable its EscapedMode property
$ADS_ESCAPEDMODE_ON = 2
$ADS_SETTYPE_DN = 4
$ADS_FORMAT_X500_DN = 7
$Pathname = new-object -comobject "Pathname"
[Void] $Pathname.GetType().InvokeMember("EscapedMode", "SetProperty", $NULL, $Pathname, $ADS_ESCAPEDMODE_ON)

# Returns correctly escaped DN using Pathname object
function Get-*********** {
 param(
 [String] $distinguishedName
 )
 [Void] $Pathname.GetType().InvokeMember("Set", "InvokeMethod", $NULL, $Pathname, ($distinguishedName, $ADS_SETTYPE_DN))
 $Pathname.GetType().InvokeMember("Retrieve", "InvokeMethod", $NULL, $Pathname, $ADS_FORMAT_X500_DN)
}

# Returns a property from a ResultPropertyCollection if it defined
function Get-SearchResultProperty {
 param(
 [System.DirectoryServices.ResultPropertyCollection] $properties,
 [String] $propertyName
 )
 if ( $properties[$propertyName] ) {
 $properties[$propertyName][0]
 }
 else {
 ""
 }
}

# Returns a property from a DirectoryEntry if it defined
function Get-DirEntryProperty {
 param(
 [System.DirectoryServices.DirectoryEntry] $dirEntry,
 [String] $propertyName
 )
 if ( $dirEntry.$propertyName ) {
 $dirEntry.$propertyName[0]
 }
 else {
 ""
 }
}

write-progress $ScriptName "Enumerating groups"
$domain = [ADSI] ""
$searcher = [ADSISearcher] "(objectClass=group)"
$searcher.SearchRoot = $domain
$searcher.PageSize = $PageSize
$searcher.SearchScope = "subtree"; 
$searcher.PropertiesToLoad.AddRange(@("name","grouptype","distinguishedname","description","managedby","member"))
$searchResults = $searcher.FindAll()
$groupCounter = 0
$groupCount = $searchResults.Count
foreach ( $searchResult in $searchResults ) {
 $properties = $searchResult.Properties
 $domainName = "domainname"
 $groupName = Get-SearchResultProperty $properties "name"
 $groupType = Get-SearchResultProperty $properties "grouptype"
 if ( ($groupType -band $ADS_GROUP_TYPE_SECURITY_ENABLED) -ne 0 ) {
 $groupTypeString = "Security"
 }
 else {
 $groupTypeString = "Distribution"
 }
 $groupDescription = Get-SearchResultProperty $properties "description"
 $groupDN = Get-SearchResultProperty $properties "distinguishedname"
 $groupManagedBy = Get-SearchResultProperty $properties "managedby"
 $member = $properties["member"]
 if ( $member ) {
 $memberCounter = 0
 $memberCount = ($member | measure-object).Count
 foreach ( $memberDN in $member ) {
 $memberDirEntry = [ADSI] "LDAP://$(Get-*********** $memberDN)"
 "" | select-object '
 @{Name = "Domain"; Expression = {$domainName}},
 @{Name = "Group Name"; Expression = {$groupName}},
 @{Name = "Type"; Expression = {$groupTypeString}},
 @{Name = "Description"; Expression = {$groupDescription}},
 @{Name = "Distinguished Name"; Expression = {$groupDN}},
 @{Name = "Managed By"; Expression = {$groupManagedBy}},
 @{Name = "Members"; Expression = {$memberDN}},
 @{Name = "Full Name"; Expression = {Get-DirEntryProperty $memberDirEntry "name"}},
 @{Name = "User Name"; Expression = {Get-DirEntryProperty $memberDirEntry "samaccountname"}},
 @{Name = "Display Name"; Expression = {Get-DirEntryProperty $memberDirEntry "displayname"}}
 $memberCounter++
 $memberPercent = ($memberCounter / $memberCount) * 100 -as [Int]
 $params = @{
 "Activity" = $ScriptName
 "Completed" = $memberPercent -eq 100
 "CurrentOperation" = "Enumerating '$groupDN'"
 "PercentComplete" = $memberPercent
 "Status" = "Groups: {0}/{1} [{2:P2}] - Members: {3}/{4} [{5:P2}]" -f
 $groupCounter,
 $groupCount,
 ($groupCounter / $groupCount),
 $memberCounter,
 $memberCount,
 ($memberCounter / $memberCount)
 }
 write-progress @params
 }
 }
 else {
 # Group contains no members
 "" | select-object '
 @{Name = "Domain"; Expression = {$domainName}},
 @{Name = "Group Name"; Expression = {$groupName}},
 @{Name = "Type"; Expression = {$groupTypeString}},
 @{Name = "Description"; Expression = {$groupDescription}},
 @{Name = "Distinguished Name"; Expression = {$groupDN}},
 @{Name = "Managed By"; Expression = {$groupManagedBy}},
 @{Name = "Members"; Expression = {""}},
 @{Name = "Full Name"; Expression = {""}},
 @{Name = "User Name"; Expression = {""}},
 @{Name = "Display Name"; Expression = {""}}
 }
 $groupCounter++
 $groupPercent = ($groupCounter / $groupCount) * 100 -as [Int]
 $params = @{
 "Activity" = $ScriptName
 "Completed" = $groupPercent -eq 100
 "CurrentOperation" = "Enumerating '$groupDN'"
 "PercentComplete" = $groupPercent
 "Status" = "Groups: {0}/{1} [{2:P2}]" -f
 $groupCounter,
 $groupCount,
 ($groupCounter / $groupCount)
 }
 write-progress @params
 # Periodically force garbage collection to reduce memory usage
 if ( ($groupCounter % $PageSize) -eq 0 ) {
 [GC]::Collect()
 [GC]::WaitForPendingFinalizers()
 }
} 
$searchResults.Dispose()

EDIT: Я попытался использовать эту строку, перед строкой, содержащей "поддерево":

$searcher.Filter = "(member:1.2.840.113556.1.4.1941:=*)"

и попытался отредактировать эту строку:

$searcher = [ADSISearcher] "(objectClass=group)"

к этому

$searcher = [ADSISearcher] "(&(objectClass=group)(memberof:1.2.840.113556.1.4.1941L:=*))"

Ни одна из них не работает, она сразу же возвращается без вывода, по-видимому, поскольку фильтр ничего не набирает. У меня не было фильтра раньше, потому что я хотел все

1 ответ

Для этого используется фильтр LDAP (1.2.840.113556.1.4.1941):

Соответствие правила LDAP в цепочке

licensed under cc by-sa 3.0 with attribution.