Get-ADPrincipalGroupMembership发生未指定的错误

时间:2019-11-26 18:32:53

标签: powershell active-directory

在Windows 10(x64)计算机上,Get-ADPrincipalGroupMembership命令出现错误。我已经按照int this文档中的指定安装了必需的RSAT-“ Active Directory域服务和轻型目录服务工具”和“服务器管理器”依赖项。我可以执行Get-AdUser并查看结果,但Get-ADPrincipalGroupMembership抛出以下错误。

PS C:\Users\JYOTHI> Get-ADPrincipalGroupMembership jyothi
Get-ADPrincipalGroupMembership : An unspecified error has occurred
At line:1 char:1
+ Get-ADPrincipalGroupMembership gapalani
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (jyothi:ADPrincipal) [Get-ADPrincipalGroupMembership], ADException
    + FullyQualifiedErrorId : ActiveDirectoryServer:0,Microsoft.ActiveDirectory.Management.Commands.GetADPrincipalGroupMembership

我可以尝试其他方式

(Get-Aduser jyothi -Properties MemberOf | Select MemberOf).MemberOf

但想知道Get-ADPrincipalGroupMembership的解决方法

2 个答案:

答案 0 :(得分:0)

Get-ADPrincipalGroupMembership-身份“ jyothi”

答案 1 :(得分:0)

您已经注意到,如果引用对象的名称包含某些字符,或者如果该引用对象是其名称中包含某些字符的一个或多个组的成员,则Get-ADPrincipalGroupMembership将失败并显示模糊错误。

我没有确切的证据,但是我的测试表明,根本的问题是Get-ADPrincipalGroupMembership在内部使用ADSI,并且无法正确地转义包含characters that need to be escaped的专有名称。 (如果是这种情况,Microsoft应该使用IADsPathname interface正确地转义名称。这对他们来说是一个令人尴尬的疏忽。)

不幸的是,此问题使cmdlet损坏,无法在生产环境中使用。

这是一个相对较短的PowerShell脚本,它不受此困扰,并且还支持检索递归组成员身份:

# Get-ADGroupMembership.ps1
# Written by Bill Stewart

#requires -version 2

# Version history:
# 1.0 (2019-12-02)
# * Initial version. Only searches the current domain.

<#
.SYNOPSIS
Gets the distinguished names of the Active Directory groups that have a specified object as a member.

.DESCRIPTION
Gets the distinguished names of the Active Directory groups that have a specified object, represented by the -Identity parameter, as a member.

.PARAMETER Identity
Specifies an Active Directory object. You can specify either the distinguishedName or the sAMAccountName of the object.

.PARAMETER Recursive
Specifies to include the object's nested group memberships.

.NOTES
If you use the ActiveDirectory PowerShell module and want Microsoft.ActiveDirectory.Management.ADGroup objects as output, pipe this command's output to the Get-ADGroup cmdlet.

.EXAMPLE
Get the distinguished names of the groups that the kendyer account is a member of:
PS C:\> Get-ADGroupMembership kendyer

.EXAMPLE
Get the distinguished names of the groups that the kendyer account is a member of, including nested groups:
PS C:\> Get-ADGroupMembership kendyer -Recursive

.EXAMPLE
Get the ADGroup objects representing the groups that the kendyer account is a member of (requires the Active Directory module):
PS C:\> Get-ADGroupMembership kendyer | Get-ADGroup
#>

[CmdletBinding()]
param(
  [Parameter(Mandatory = $true,ValueFromPipeline = $true)]
  [String[]] $Identity,

  [Switch] $Recursive
)

begin {
  $CommandName = $MyInvocation.MyCommand.Name

  # Set up Pathname COM object
  $ADS_ESCAPEDMODE_ON = 2
  $ADS_SETTYPE_DN = 4
  $ADS_FORMAT_X500_DN = 7
  $Pathname = New-Object -ComObject "Pathname"
  if ( -not $Pathname ) {
    return
  }
  [Void] $Pathname.GetType().InvokeMember("EscapedMode","SetProperty",$null,$Pathname,$ADS_ESCAPEDMODE_ON)

  # Outputs correctly escaped distinguished name using Pathname object
  function Get-EscapedName {
    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)
  }

  # Outputs the memberOf attribute of an object using paged search (in case
  # an object is a member of a large number of groups)
  function Get-MemberOfAttribute {
    param(
      [String] $distinguishedName,
      [Ref] $memberOf,
      [Switch] $recursive
    )
    $searcher = [ADSISearcher] "(objectClass=*)"
    $searcher.SearchRoot = [ADSI] "LDAP://$(Get-EscapedName $distinguishedName)"
    $lastQuery = $false
    $rangeStep = 1500
    $rangeLow = 0
    $rangeHigh = $rangeLow + ($rangeStep - 1)
    do {
      if ( -not $lastQuery ) {
        $property = "memberOf;range={0}-{1}" -f $rangeLow,$rangeHigh
      }
      else {
        $property = "memberOf;range={0}-*" -f $rangeLow
      }
      $searcher.PropertiesToLoad.Clear()
      [Void] $searcher.PropertiesToLoad.Add($property)
      $searchResults = $searcher.FindOne()
      if ( $searchResults.Properties.Contains($property) ) {
        foreach ( $searchResult in $searchResults.Properties[$property] ) {
          if ( $memberOf.Value.Count -gt 100 ) {
            Write-Progress `
              -Activity $CommandName `
              -Status "Getting membership of '$distinguishedName'" `
              -CurrentOperation $searchResult
          }
          if ( $recursive ) {
            if ( -not $memberOf.Value.Contains($searchResult) ) {
              Get-MemberOfAttribute $searchResult $memberOf -recursive
            }
          }
          if ( -not $memberOf.Value.Contains($searchResult) ) {
            $memberOf.Value.Add($searchResult)
          }
        }
        $done = $lastQuery
      }
      else {
        if ( -not $lastQuery ) {
          $lastQuery = $true
        }
        else {
          $done = $true
        }
      }
      if ( -not $lastQuery ) {
        $rangeLow = $rangeHigh + 1
        $rangeHigh = $rangeLow + ($rangeStep - 1)
      }
    }
    until ( $done )
    Write-Progress `
      -Activity $CommandName `
      -Status "Getting membership of '$distinguishedName'" `
      -Completed:$true
  }

  function Get-ADGroupMembership {
    [CmdletBinding()]
    param(
      [Parameter(Mandatory = $true)]
      [String] $identity,
      [Switch] $recursive
    )
    $ldapString = $identity -replace '\\','\5c' -replace '\(','\28' -replace '\)','\29' -replace '\*','\2a' -replace '\/','\2f'
    $searcher = [ADSISearcher] "(|(distinguishedName=$ldapString)(sAMAccountName=$ldapString))"
    try {
      $searchResults = $searcher.FindAll()
      if ( $searchResults.Count -gt 0 ) {
        foreach ( $searchResult in $searchResults ) {
          $memberOf = New-Object Collections.Generic.List[String]
          Get-MemberOfAttribute $searchResult.Properties["distinguishedname"][0] ([Ref] $memberOf) -recursive:$recursive
          $memberOf
        }
      }
      else {
        Write-Error "Cannot find an object with identity '$identity'." -Category ObjectNotFound
      }
    }
    catch {
      Write-Error -ErrorRecord $_
    }
    finally {
      $searchResults.Dispose()
    }
  }
}

process {
  foreach ( $IdentityItem in $Identity ) {
    Get-ADGroupMembership $IdentityItem -recursive:$Recursive
  }
}

我还将此脚本添加为public gist on github,以防万一需要修复或添加新功能。