PowerShell中的ADSI报告 - 递归组

时间:2014-09-23 11:23:47

标签: powershell recursion active-directory adsi

我在 PowerShell 中有这个代码,它会查看组和用户,并使用我想要的字段创建制表符分隔的txt文件。

然而,它只能找到一半的信息。我正在尝试替换生成相同报告的另一个流程,此报告收集大约580,000行数据,而此 PowerShell 报告仅生成大约300,000个。
我想我需要递归地查看群组,但我不知道该怎么做。

代码:

#requires -version 2

$ScriptName = $MyInvocation.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-EscapedPath {
  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's 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's 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-EscapedPath $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()

编辑: 我尝试使用这一行,就在包含"子树":

的行之前
$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 个答案:

答案 0 :(得分:0)

有一个LDAP过滤器(1.2.840.113556.1.4.1941):

LDAP Matching Rule in Chain