Reputation: 4331
PowerShell's Get-ADGroupMember
cmdlet returns members of a specific group. Is there a cmdlet or property to get all the groups that a particular user is a member of?
Upvotes: 210
Views: 1634406
Reputation: 2550
I really loved the Answer Canoas provided for not relying on any module.
I also really liked the recursive solutions suggested, so I wrote a version that I think would be appreciated (if you scrolled down enough to see it).
function Get-MyADPrincipalGroupMembership{
[CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='Medium')]param(
[Parameter(Position=0)]
[string]$Name = $env:USERNAME,
[Parameter(Position=1)]
[string]$Type = "User",
[Alias("Recursive")]
[switch]$Recurse,
[int]$MaxDepth = -1,
[int]$MinDepth = 0
)
## assumeRecurse Recurse MaxDepth MinDepth
## 0 0 -1 0 ($MaxDepth -eq -1 -and ($Recurse -and $MinDepth -eq 0 -or $MinDepth -gt 0))
## 1 1 -1 0 ($MaxDepth -eq -1 -and ($Recurse -and $MinDepth -eq 0 -or $MinDepth -gt 0))
## 1 N/A -1 1 ($MaxDepth -eq -1 -and ($Recurse -and $MinDepth -eq 0 -or $MinDepth -gt 0))
## 1 N/A -1 2 ($MaxDepth -eq -1 -and ($Recurse -and $MinDepth -eq 0 -or $MinDepth -gt 0))
## 0 N/A 0 0 ($MaxDepth -gt 0 -and $MaxDepth -ge $MinDepth)
## 1 N/A 1 0 ($MaxDepth -gt 0 -and $MaxDepth -ge $MinDepth)
## 1 N/A 1 0 ($MaxDepth -gt 0 -and $MaxDepth -ge $MinDepth)
## 1 N/A 2 0 ($MaxDepth -gt 0 -and $MaxDepth -ge $MinDepth)
## 1 N/A 1 1 ($MaxDepth -gt 0 -and $MaxDepth -ge $MinDepth)
## 1 N/A 2 1 ($MaxDepth -gt 0 -and $MaxDepth -ge $MinDepth)
## 0 N/A 1 2 ($MaxDepth -gt 0 -and $MaxDepth -ge $MinDepth)
$local:assumeRecurse =
($MaxDepth -eq -1 -and ($Recurse -and $MinDepth -eq 0 -or $MinDepth -gt 0)) -or
($MaxDepth -gt 0 -and $MaxDepth -ge $MinDepth)
Write-Verbose "$(Split-Path -LeafBase $PSCommandPath) Called with $("-Name:$Name".PadRight(48)) $("-Type:$Type".PadRight(12))$($Recurse ? ' -Recurse' : '')$($MaxDepth -ne -1 ? " -MaxDepth $MaxDepth" : '')$($MinDepth -gt 0 ? " -MinDepth $MinDepth" : '') | assumeRecurse = $assumeRecurse"
$local:srch = ([System.DirectoryServices.DirectorySearcher](
"(&(objectCategory=$($Type))(samAccountName=$($Name)))"
)).FindOne();
if( -not $srch ) { throw "(&(objectCategory=$($Type))(samAccountName=$($Name))) not found"; return 1 }
$local:ADSearchResults = $srch.GetDirectoryEntry()
function orderGroups { param(
[Parameter(Mandatory,Position=1)]
$InputObject,
[switch]$ForceAll
)
$local:results = @()
$results += , $( foreach( $local:ou in $InputObject ) {
if ($ou -eq 'Groups') {
if( $ForceAll ) { "0$ou" } else { return "0" }
} else {
"1$ou"
}
})
return ($results | Sort-Object ) -join ','
}
function orderTypeLevel { param(
[Parameter(Mandatory,Position=0)]
$InputObject
)
"$($InputObject.TypeLevel[0])$($InputObject.TypeLevel[1] -eq 'User' ? 0 : 1)$($InputObject.TypeLevel[1])"
}
$local:results = @()
$results += $ADSearchResults.memberOf | ForEach-Object {
$local:searchEntry = [ordered]@{ TypeLevel = $Type; Principal = $Name };
$_ -split ',' | ForEach-Object {
$local:record = $_ -split '=';
if( $record[0] -notin @('DC') ) {
$searchEntry[$record[0]] += @($record[1])
}
}
$searchEntry.CN = $searchEntry.CN[0]
# Remove Domain and sort OUs
if( $searchEntry.OU ) {
$searchEntry.OU = $searchEntry.OU | Select-Object -SkipLast 1 | Sort-Object { orderGroups $_ }
}
#$searchEntry.Order = orderGroups $searchEntry.OU -ForceAll
[PSCustomObject]$searchEntry
}
if ( $assumeRecurse ) {
$local:groups = $results | Where-Object { "Groups" -in $_.OU }
if( $MinDepth -gt 0 ) { $results = @() }
$local:RecursiveParams = @{
Recurse = $Recurse
Type = "Group"
MinDepth = $MinDepth - ($MinDepth -gt 0 ? 1 : 0)
}
if( $MaxDepth -gt 0 ) { $RecursiveParams.MaxDepth = $MaxDepth - 1 }
foreach( $local:group in $groups ) {
try {
$results += Get-MyADPrincipalGroupMembership -Name $group.CN @RecursiveParams
} catch {
Write-Warning "Failed to recurse into $($group.CN) ($_)"
}
}
}
$local:debugResults = @()
$results | ForEach-Object {
if( $_.TypeLevel -is [string] ) {
$_.TypeLevel = @(0, $_.TypeLevel)
} else {
$_.TypeLevel[0] += 1
}
$_
} | Group-Object CN | ForEach-Object {
$_.Group |
Sort-Object @{E={ orderTypeLevel $_ }},Principal,CN |
Select-Object -First 1
} | Sort-Object -OutVariable debugResults { "$(orderGroups $_.OU)#$(orderTypeLevel $_)#$($_.Principal)$($_.CN)" }
# $debugResults | Select-Object *,@{E={ "$(orderGroups $_.OU)#$(orderTypeLevel $_)#$($_.Principal)$($_.CN)" }} | Format-Table | Out-String | % { Write-Host -ForegroundColor Cyan $_ }
Write-Verbose "$(($debugResults | Measure-Object).Count) records returned"
Remove-Variable debugResults
}
Upvotes: 0
Reputation: 34979
There is no need for PowerShell, you could use the command line tool gpresult
as follows:
gpresult /USER domain\username /R
You may omit the /USER
portion to display the information for the currently logged on user:
gpresult /R
Example output:
Microsoft (R) Windows (R) Operating System Group Policy Result tool v2.0 © Microsoft Corporation. All rights reserved. Created on 10/01/2024 at 10:14:48 RSOP data for DOMAIN\username on SYSTEM : Logging Mode ------------------------------------------------------- OS Configuration: Member Workstation OS Version: 10.0.19045 Site Name: N/A Roaming Profile: N/A Local Profile: C:\Users\username Connected over a slow link?: No USER SETTINGS -------------- CN=full name,OU=organisation unit,DC=some Last time Group Policy was applied: 10/01/2024 at 09:00:00 Group Policy was applied from: server Group Policy slow link threshold: 500 kbps Domain Name: MEDEL Domain Type: Windows 2008 or later Applied Group Policy Objects ----------------------------- usrPolWindowsAccounts (list of applied group policies) The following GPOs were not applied because they were filtered out ------------------------------------------------------------------- usrPolGermanGermany Filtering: Denied (Security) (list of denied group policies) The user is a part of the following security groups --------------------------------------------------- Domain Users Everyone Remote Desktop Users BUILTIN\Users NT AUTHORITY\INTERACTIVE CONSOLE LOGON NT AUTHORITY\Authenticated Users This Organization LOCAL secUsersEnglish (list of security groups)
In contrast to the net user
command (as suggested in user4511672's answer), the group names are not truncated.
Upvotes: 1
Reputation: 3852
Get-ADPrincipalGroupMembership
from the Active Directory module will do this. You'll need that module, or RSAT on Windows 10+, installed to run the command below.
Get-ADPrincipalGroupMembership username | select name
name
----
Domain Users
Domain Computers
Workstation Admins
Company Users
Company Developers
AutomatedProcessingTeam
Upvotes: 382
Reputation: 1096
First, import the ActiveDirectory module:
Import-Module ActiveDirectory
Then issue this command:
Get-ADGroupMember -Identity $group | foreach-object {
Write-Host $_.SamAccountName
}
This will display the members of the specified group.
Upvotes: 4
Reputation: 147
(Get-ADUser $env:username -Properties MemberOf).MemberOf | % {$_.split(",")[0].replace("CN=","")}
Domain Users
Domain Computers
Workstation Admins
Company Users
Company Developers
AutomatedProcessingTeam
Upvotes: 2
Reputation: 657
For LOCAL users and groups (ie not in Active Directory), and if you don't want to, or aren't allowed to, or can't install RSAT and/or Install-WindowsFeature RSAT-AD-PowerShell
and/or import-module activedirectory
then here's a pure, pre-installed powershell (5.1+) way to do it.
(Note: Get-LocalGroup*
used below are only available Powershell v5.1 and above. "...v5.1 was released along with the Windows 10 Anniversary Update on August 2, 2016, and in Windows Server 2016. ...[F]or Windows 7, Windows Server 2008, Windows Server 2008 R2, Windows Server 2012, and Windows Server 2012 R2 [it] was released on January 19, 2017." (wikipedia))
$username = "user002"
Get-LocalGroup | ForEach-Object {
# the usernames are returned in the string form "computername\username"
if (Get-LocalGroupMember -Group $_ | Where-Object name -like "*\$username") {
$_.name
}
}
Example output:
Administrators
Users
Upvotes: 4
Reputation: 2139
Single line, no modules necessary, uses current logged user:
(New-Object System.DirectoryServices.DirectorySearcher("(&(objectCategory=User)(samAccountName=$($env:username)))")).FindOne().GetDirectoryEntry().memberOf
Kudos to this vbs/powershell article: http://technet.microsoft.com/en-us/library/ff730963.aspx
Upvotes: 154
Reputation: 13
I use this simple oneliner to recursively search all the groups a user is member of:
Get-ADPrincipalGroupMembership $UserName | foreach-object { Get-ADPrincipalGroupMembership $_.SamAccountName | select SamAccountName }
To filter the groups to find out if user is member of a specific group i use this:
if ( Get-ADPrincipalGroupMembership $UserName | foreach-object { Get-ADPrincipalGroupMembership $_.SamAccountName | select SamAccountName } | where-object {$_.SamAccountName -like "*$Groupname*"} ) { write-host "Found" } else { write-host "not a member of group $Groupname" }
Upvotes: 0
Reputation: 3224
This should provide you the details for current user. Powershell not needed.
whoami /groups
Upvotes: 29
Reputation: 530
When you do not have privileges to consult other member groups but you do have the privilege to consult group members, you can do the following to build a map of which user has access to which groups.
$groups = get-adgroup -Filter * | sort name | select Name
$users = @{}
foreach($group in $groups) {
$groupUsers = @()
$groupUsers = Get-ADGroupMember -Identity $group.Name | Select-Object SamAccountName
$groupUsers | % {
if(!$users.ContainsKey($_.SamAccountName)){
$users[$_.SamAccountName] = @()
}
($users[$_.SamAccountName]) += ($group.Name)
}
}
Upvotes: 1
Reputation: 1137
While there are many excellent answers here, there is one which I was personally looking for that was missing. Once I figured it out - I thought I should post it in case I want to find it later, or it actually manages to help someone else at some point:
Get-ADPrincipalGroupMembership username | Format-Table -auto
A second approach for presenting this is to specify the individual columns you are interested in eg:
Get-ADPrincipalGroupMembership username | select name, GroupScope, GroupCategory
This gives all the AD groups the username belongs to - but also presents all of the default properties of each group formatted nicely as a table.
The key benefit this gives you is you can see at a glance which are distribution lists, & which are Security groups. You can further see at a glance which are Universal, which are DomainLocal & which are Global.
Why would you care about this last bit?
Upvotes: 9
Reputation: 101
Studying all comments presented gave me a starting point (thanks for such) but left me with several unresolved issues. As result here is my answer. The code snippet provided does a little more than what is asked for but it provides helpful debugging info.
[array] $script:groupsdns = @()
function Get-ADPrincipalGroupMembershipRecursive()
{
Param( [string] $dn, [int] $level = 0, [array] $groups = @() )
#if(($groupsdns | where { $_.DistinguishedName -eq $dn }).Count -ne 0 ) { return $groups } # dependency on next statement
#$groupsdns += (Get-ADObject $dn -Properties MemberOf) # Get-ADObject cannot find an object with identity
if ($script:groupsdns.Contains($dn)) { return $groups }
$script:groupsdns += $dn
$mo = $Null
$mo = Get-ADObject $dn -Properties MemberOf # Get-ADObject cannot find an object with identity
$group = ($dn + " (" + $level.ToString())
if ($mo -eq $Null) { $group += "!" }
$group += ")"
$groups += $group
foreach( $groupdn in $mo.MemberOf )
{
$groups = Get-ADPrincipalGroupMembershipRecursive -dn $groupdn -level ($level+1) -groups $groups
}
if ($level -le 0)
{
$primarygroupdn = (Get-ADUser -Identity $dn -Properties PrimaryGroup).PrimaryGroup
$groups = Get-ADPrincipalGroupMembershipRecursive -dn $primarygroupdn -level ($level+1) -groups $groups
}
return $groups
}
$adusergroups = Get-ADPrincipalGroupMembershipRecursive -dn $aduser.DistinguishedName
$adusergroups | ft -AutoSize | `
Out-File -Width 512 Get-ADPrincipalGroupMembershipRecursive.txt #-Append #-Wrap # | Sort-Object -Property Name
Upvotes: 2
Reputation: 4297
If you cannot get Get-ADPrincipalGroupMembership to work for you could try logging in as that user then use.
$id = [Security.Principal.WindowsIdentity]::GetCurrent()
$groups = $id.Groups | foreach-object {$_.Translate([Security.Principal.NTAccount])}
$groups | select *
Upvotes: 13
Reputation: 379
Putting this here for future reference. I'm in the midst of an email migration. I need to know each user account and its respective group membership, and also I need to know each group and its respective members.
I'm using the code block below to output a CSV for each user's group membership.
Get-ADUser -Filter * |`
ForEach-Object { `
$FileName = $_.SamAccountName + ".csv" ; `
$FileName ; `
Get-ADPrincipalGroupMembership $_ | `
Select-Object -Property SamAccountName, name, GroupScope, GroupCategory | `
Sort-Object -Property SamAccountName | `
Export-Csv -Path $FileName -Encoding ASCII ; `
}
The export process for the groups and their respective members was a little convoluted, but the below works. The output filenames include the type of group. Therefore, the email distribution groups I need are/should be the Universal and Global Distribution groups. I should be able to just delete or move the resulting TXT files I don't need.
Get-ADGroup -Filter * | `
Select-Object -Property Name, DistinguishedName, GroupScope, GroupCategory | `
Sort-Object -Property GroupScope, GroupCategory, Name | `
Export-Csv -Path ADGroupsNew.csv -Encoding ASCII
$MyCSV = Import-Csv -Path .\ADGroupsNew.csv -Encoding ASCII
$MyCSV | `
ForEach-Object { `
$FN = $_.GroupScope + ", " + $_.GroupCategory + ", " + $_.Name + ".txt" ; `
$FN ; `
Get-ADGroupMember -Identity $_.DistinguishedName | `
Out-File -FilePath $FN -Encoding ASCII ; $FN=""; `
}
Upvotes: 0
Reputation: 1217
With user input and fancy output formatting:
[CmdletBinding(SupportsShouldProcess=$True)]
Param(
[Parameter(Mandatory = $True)]
[String]$UserName
)
Import-Module ActiveDirectory
If ($UserName) {
$UserName = $UserName.ToUpper().Trim()
$Res = (Get-ADPrincipalGroupMembership $UserName | Measure-Object).Count
If ($Res -GT 0) {
Write-Output "`n"
Write-Output "$UserName AD Group Membership:"
Write-Output "==========================================================="
Get-ADPrincipalGroupMembership $UserName | Select-Object -Property Name, GroupScope, GroupCategory | Sort-Object -Property Name | FT -A
}
}
Upvotes: 0
Reputation: 2787
Almost all above solutions used the ActiveDirecotry
module which might not be available by default in most cases.
I used below method. A bit indirect, but served my purpose.
List all available groups
Get-WmiObject -Class Win32_Group
And then list the groups the user belongs to
[System.Security.Principal.WindowsIdentity]::GetCurrent().Groups
Comparison can then be done via checking through the SIDs
. This works for the logged in user. Please correct me if I am wrong. Completely new to PowerShell, but had to get this done for a work commitment.
Upvotes: 0
Reputation: 14745
To get it recursive, you can use:
<#
.SYNOPSIS
Get all the groups that a user is MemberOf.
.DESCRIPTION
This script retrieves all the groups that a user is MemberOf in a recursive way.
.PARAMETER SamAccountName
The name of the user you want to check #>
Param (
[String]$SamAccountName = 'test',
$DomainUsersGroup = 'CN=Domain Users,CN=Users,DC=domain,DC=net'
)
Function Get-ADMemberOf {
Param (
[Parameter(ValueFromPipeline)]
[PSObject[]]$Group,
[String]$DomainUsersGroup = 'CN=Domain Users,CN=Users,DC=grouphc,DC=net'
)
Process {
foreach ($G in $Group) {
$G | Get-ADGroup | Select -ExpandProperty Name
Get-ADGroup $G -Properties MemberOf| Select-Object Memberof | ForEach-Object {
Get-ADMemberOf $_.Memberof
}
}
}
}
$Groups = Get-ADUser $SamAccountName -Properties MemberOf | Select-Object -ExpandProperty MemberOf
$Groups += $DomainUsersGroup
$Groups | Get-ADMemberOf | Select -Unique | Sort-Object
Upvotes: 1
Reputation: 3461
Get group membership for a user:
$strUserName = "Primoz"
$strUser = get-qaduser -SamAccountName $strUserName
$strUser.memberof
See Get Group Membership for a User
But also see Quest's Free PowerShell Commands for Active Directory.
[Edit: Get-ADPrincipalGroupMembership command is included in Powershell since v2 with Windows 2008 R2. See kstrauss' answer below.]
Upvotes: 5
Reputation: 601
I couldn't get the following to work for a particular user:
Get-ADPrincipalGroupMembership username
It threw an error that I was not willing to troubleshoot.
I did however come up with a different solution using Get-ADUser. I like it a bit better because if you don't know the account name then you can get it based off of a wildcard on the user's actual name. Just fill in PartOfUsersName and away it goes.
#Get the groups that list of users are the member of using a wildcard search
[string]$UserNameLike = "*PartOfUsersName*" #Use * for wildcards here
[array]$AccountNames = $(Get-ADUser -Filter {Name -like $UserNameLike}).SamAccountName
ForEach ($AccountName In $AccountNames) {
Write-Host "`nGETTING GROUPS FOR" $AccountName.ToUpper() ":"
(Get-ADUser -Identity $AccountName -Properties MemberOf|select MemberOf).MemberOf|
Get-ADGroup|select Name|sort name
}
Huge props to schmeckendeugler and 8DH for getting me to this solution. +1 to both of you.
Upvotes: 1
Reputation: 41
Use:
Get-ADPrincipalGroupMembership username | select name | export-CSV username.csv
This pipes output of the command into a CSV file.
Upvotes: 4
Reputation: 41
It is just one line:
(get-aduser joe.bloggs -properties *).memberof
end of :)
Upvotes: 3
Reputation: 25810
Get-Member is not for getting user's group membership. If you want to get a list of groups a user belongs to on the local system, you can do so by:
$query = "ASSOCIATORS OF {Win32_Account.Name='DemoUser1',Domain='DomainName'} WHERE ResultRole=GroupComponent ResultClass=Win32_Account"
Get-WMIObject -Query $query | Select Name
In the above query, replace DemoUser1 with the username you want and the DomainName with either your local computer name or domain name.
Upvotes: 5
Reputation: 24470
The below works well:
get-aduser $username -Properties memberof | select -expand memberof
If you have a list of users:
$list = 'administrator','testuser1','testuser2'
$list | `
%{
$user = $_;
get-aduser $user -Properties memberof | `
select -expand memberof | `
%{new-object PSObject -property @{User=$user;Group=$_;}} `
}
Upvotes: 2
Reputation: 41
No need for long scripts when it is a simple one liner..
QUEST Command
(Get-QADUser -Identity john -IncludedProperties MemberOf | Select-Object MemberOf).MemberOf
MS AD Command
(GET-ADUSER –Identity john –Properties MemberOf | Select-Object MemberOf).MemberOf
I find the MS AD cmd is faster but some people like the Quest ones better..
Steve
Upvotes: 4
Reputation: 1
This is the simplest way to just get the names:
Get-ADPrincipalGroupMembership "YourUserName"
# Returns
distinguishedName : CN=users,OU=test,DC=SomeWhere
GroupCategory : Security
GroupScope : Global
name : testGroup
objectClass : group
objectGUID : 2130ed49-24c4-4a17-88e6-dd4477d15a4c
SamAccountName : testGroup
SID : S-1-5-21-2114067515-1964795913-1973001494-71628
Add a select statement to trim the response or to get every user in an OU every group they are a user of:
foreach ($user in (get-aduser -SearchScope Subtree -SearchBase $oupath -filter * -Properties samaccountName, MemberOf | select samaccountName)){
Get-ADPrincipalGroupMembership $user.samaccountName | select name}
Upvotes: 0
Reputation: 769
Get-ADUser -Filter { memberOf -RecursiveMatch "CN=Administrators,CN=Builtin,DC=Fabrikam,DC=com" } -SearchBase "CN=Administrator,CN=Users,DC=Fabrikam,DC=com" -SearchScope Base
## NOTE: The above command will return the user object (Administrator in this case) if it finds a match recursively in memberOf attribute.
Upvotes: 1
Reputation: 909
A more concise alternative to the one posted by Canoas, to get group membership for the currently-logged-on user.
I came across this method in this blog post: http://www.travisrunyard.com/2013/03/26/auto-create-outlook-mapi-user-profiles/
([ADSISEARCHER]"samaccountname=$($env:USERNAME)").Findone().Properties.memberof
An even better version which uses a regex to strip the LDAP guff and leaves the group names only:
([ADSISEARCHER]"samaccountname=$($env:USERNAME)").Findone().Properties.memberof -replace '^CN=([^,]+).+$','$1'
More details about using the [ADSISEARCHER] type accelerator can be found on the scripting guy blog: http://blogs.technet.com/b/heyscriptingguy/archive/2010/08/24/use-the-powershell-adsisearcher-type-accelerator-to-search-active-directory.aspx
Upvotes: 63
Reputation: 11
Get-QADUser -SamAccountName LoginID | % {$_.MemberOf } | Get-QADGroup | select name
Upvotes: 1