I am stuck trying to figure out how to get all Active Directory groups that are empty. I came up with this command, which selects groups that have no Members and aren't a MemberOf anything.
Get-QADGroup -GroupType Security -SizeLimit 0 | where-object {$_.Members.Count -eq 0 -and $_.MemberOf.Count -eq 0} | select GroupName, ParentContainer | Export-Csv c:\emptygroups.csv
This is mostly correct, but it's saying certain groups like the default group Domain Computers is empty, but it isn't empty. This particular group has only members that are computers, but it appears that other groups that only have computers as well aren't selected.
Does anyone know why this command is pulling in some that have members?
The Get-QADGroup cmdlet has a parameter -Empty. The description in the help hints at the reason these default groups are being returned:
Note: A group is considered empty if it has the "member" attribute not set. So, this parameter can retrieve a group that has only those members for which the group is set as the primary group. An example is the Domain Users group, which normally is the primary group for any user account while having the "member" attribute not set.
I'm not really familiar with the Quest stuff, but I was able to find empty groups this way, (probably not the most efficient):
Get-ADGroup -Filter {GroupCategory -eq 'Security'} | ?{#(Get-ADGroupMember $_).Length -eq 0}
This line will do (use Import-Module ActiveDirectory first):
Get-ADGroup -Filter * -Properties Members | where { $_.Members.Count -eq 0 }
This version will display only the groupcategory and SAMaccountname. Name could also be used in place of samaccountname. The groupcategory will show you if its a security group or a DL.
Get-ADGroup –Filter * -Properties Members | where { $_.Members.Count –eq 0 } |select groupcategory,samaccountname >c:\temp\nomembers.csv
Actually it will be a lost faster in environments with multiple domains, large number of groups (and large number of users) to run it as a script.
Note: you will need to have PowerShell Active directory module loaded (import-module activedirectory)
$domains = Get-ADForest|select -ExpandProperty domains
$empties = #()
$oops = #()
foreach ($d in $domains){
$groups = get-adgroup -filter * -server $d
foreach ($g in $groups){
$q = get-adgroup $g -properties members -server $d|select -expandproperty members
If(!$?){$oops += $g
write-host $g.name}
if ($q -eq $null) {$empties += $g}
}
}
$empties|select name,distinguishedname|export-csv .\empties.csv
$oops|select name,distinguishedname|export-csv .\oops.csv
This worked for me.
Get-ADGroup -Filter {GroupCategory -eq 'Security'} -Properties Members | where { $_.Members.Count -eq 0 } | Select Name | Sort-Object Name
Was able to get the values properly by piping in Get-QADGroupMember and getting the count of Members and MemberOf which could then be filtered. This seems terribly inefficient, but it serves the purpose to get the counts needed.
Get-QADGroup -SizeLimit 0 | Select-Object Name,#{n='MemberCount';e={ (Get-QADGroupMember $_ -SizeLimit 0 | Measure-Object).Count}},#{n='MemberOfCount';e={ ((Get-QADGroup $_).MemberOf | Measure-Object).Count}}
If anyone has a better way to do this, do tell.
Related
I am trying to pull groups in from a text file and one of my groups is too large, 80,000 people.
How do I get this to work l, it outputs how I want it.
$groups = Get-Content c:\temp\ADGroups.txt
foreach($group in $groups) {
#(Get-ADGroup $group -Properties Member| Select-Object -ExpandProperty Member).Count
Get-ADGroupMember -Identity $group |
Get-ADObject -Properties Name, DisplayName |
Select-Object -Property #{n="Username";e={$_.Name}}, DisplayName,
#{n="AD Group";e={$group}} |
Export-Csv C:\Users\Desktop\GroupsInfo.CSV -NoTypeInformation -Append
}
The number of objects that Get-ADGroupMember can return is restricted by a limit in the ADWS (Active Directory Web Services):
MaxGroupOrMemberEntries
5000
Specifies the maximum number of group members (recursive or non-recursive), group memberships, and authorization groups that can be retrieved by the Active Directory module Get-ADGroupMember, Get-ADPrincipalGroupMembership, and Get-ADAccountAuthorizationGroup cmdlets. Set this parameter to a higher value if you anticipate these cmdlets to return more than 5000 results in your environment.
According to this thread you should be able to work around it by querying group objects and expanding their member property (if you can't increase the limit on the service):
Get-ADGroup $group -Properties Member |
Select-Object -Expand Member |
Get-ADUser -Property Name, DisplayName
Beware, though, that this is likely to be slow, because you'll be sending thousands of requests. It might be better to build a hashtable of all users:
$users = #{}
Get-ADUser -Filter '*' -Property Name, DisplayName | ForEach-Object {
$users[$_.DistinguishedName] = $_
}
so that you can look them up by their distinguished name:
Get-ADGroup $group -Properties Member |
Select-Object -Expand Member |
ForEach-Object { $users[$_] }
I was hitting the 5000 limit with Get-ADGroupMember.
You can use Get-ADUser with the -LDAPFilter parameter to get group members. It's quick and supports >5000 entries.
$groups = #(
"group1"
"group2"
"group3"
)
Foreach ($group in $groups) {
Get-ADUser -LDAPFilter "(&(objectCategory=user)(memberof=CN=$group,OU=Groups,OU=rest,DC=of,DC=distinguished,DC=name))" | Export-Csv "C:\$group.csv"
}
It looks like you can build up complex filters with this method. I needed to quickly return enabled members from some extremely large groups. The filter I used for this was:
"(&(objectCategory=user)(!useraccountcontrol:1.2.840.113556.1.4.803:=2)(memberof=CN=$group,OU=Groups,OU=rest,DC=of,DC=distinguished,DC=name))"
I hear this is a limitation of the AD Webservices that actually service the requests from powershell cmdlets. The maximum size is 5000. But you can try the dsget command, although you will need to get a little creative.
$GroupDN = (Get-ADGroup -Identity $Group).DistinguishedName will give you the DN of the group.
Use the DSget like this.
$members = DSget group $GroupDN -members This will give you the list of DNs of all members.
Feed that to a Get-ADUser cmdlet in a pipe or foreach loop and you are good to go.
You would need to use the -resultpagesize parameter. The highest value you can specify is 2147483647.
So:
Get-ADGroupMember -Identity $group -resultpagesize 2147483647 |
Select-Object -Property #{n="Username";e={$_.Name}}, DisplayName,
#{n="AD Group";e={$group}} |
Export-Csv C:\Users\Desktop\GroupsInfo.CSV -NoTypeInformation -Append
This is how I did mine. I needed to extract more than 25k machines from a security group.
$Groups = gc C:\Temp\Groups.txt
$results = foreach ($Group in $Groups) {
Get-ADGroup $Group -Properties Member | Select-Object -ExpandProperty Member | Get-ADObject -Properties Name
}
$results | Export-csv "C:\Temp\Groups.csv" -NoTypeInformation
This will give you all of the members of a group quickly (mine had 85k members)
$groupMembers = Get-ADGroup -Identity $group -Server $domainGroupIsIn -Properties Member | Select-Object -ExpandProperty Member ;
or if you need to filter some
$whereMatch = $recipient.DistinguishedName.Remove(0, $index); # limits to a domain or container
$groupMembers = Get-ADGroup -Identity $group -Server $domainGroupIsIn -Properties Member | Select-Object -ExpandProperty Member | Where {$_ -match $whereMatch};
Just increase the limit from ADUC --> View --> Filter Option - Maximum number of options displayed per folder.
That's it. Try again running your command. It takes me 4 days to figure out this and finally it's working.
I am trying to pull groups in from a text file and one of my groups is too large, 80,000 people.
How do I get this to work l, it outputs how I want it.
$groups = Get-Content c:\temp\ADGroups.txt
foreach($group in $groups) {
#(Get-ADGroup $group -Properties Member| Select-Object -ExpandProperty Member).Count
Get-ADGroupMember -Identity $group |
Get-ADObject -Properties Name, DisplayName |
Select-Object -Property #{n="Username";e={$_.Name}}, DisplayName,
#{n="AD Group";e={$group}} |
Export-Csv C:\Users\Desktop\GroupsInfo.CSV -NoTypeInformation -Append
}
The number of objects that Get-ADGroupMember can return is restricted by a limit in the ADWS (Active Directory Web Services):
MaxGroupOrMemberEntries
5000
Specifies the maximum number of group members (recursive or non-recursive), group memberships, and authorization groups that can be retrieved by the Active Directory module Get-ADGroupMember, Get-ADPrincipalGroupMembership, and Get-ADAccountAuthorizationGroup cmdlets. Set this parameter to a higher value if you anticipate these cmdlets to return more than 5000 results in your environment.
According to this thread you should be able to work around it by querying group objects and expanding their member property (if you can't increase the limit on the service):
Get-ADGroup $group -Properties Member |
Select-Object -Expand Member |
Get-ADUser -Property Name, DisplayName
Beware, though, that this is likely to be slow, because you'll be sending thousands of requests. It might be better to build a hashtable of all users:
$users = #{}
Get-ADUser -Filter '*' -Property Name, DisplayName | ForEach-Object {
$users[$_.DistinguishedName] = $_
}
so that you can look them up by their distinguished name:
Get-ADGroup $group -Properties Member |
Select-Object -Expand Member |
ForEach-Object { $users[$_] }
I was hitting the 5000 limit with Get-ADGroupMember.
You can use Get-ADUser with the -LDAPFilter parameter to get group members. It's quick and supports >5000 entries.
$groups = #(
"group1"
"group2"
"group3"
)
Foreach ($group in $groups) {
Get-ADUser -LDAPFilter "(&(objectCategory=user)(memberof=CN=$group,OU=Groups,OU=rest,DC=of,DC=distinguished,DC=name))" | Export-Csv "C:\$group.csv"
}
It looks like you can build up complex filters with this method. I needed to quickly return enabled members from some extremely large groups. The filter I used for this was:
"(&(objectCategory=user)(!useraccountcontrol:1.2.840.113556.1.4.803:=2)(memberof=CN=$group,OU=Groups,OU=rest,DC=of,DC=distinguished,DC=name))"
I hear this is a limitation of the AD Webservices that actually service the requests from powershell cmdlets. The maximum size is 5000. But you can try the dsget command, although you will need to get a little creative.
$GroupDN = (Get-ADGroup -Identity $Group).DistinguishedName will give you the DN of the group.
Use the DSget like this.
$members = DSget group $GroupDN -members This will give you the list of DNs of all members.
Feed that to a Get-ADUser cmdlet in a pipe or foreach loop and you are good to go.
You would need to use the -resultpagesize parameter. The highest value you can specify is 2147483647.
So:
Get-ADGroupMember -Identity $group -resultpagesize 2147483647 |
Select-Object -Property #{n="Username";e={$_.Name}}, DisplayName,
#{n="AD Group";e={$group}} |
Export-Csv C:\Users\Desktop\GroupsInfo.CSV -NoTypeInformation -Append
This is how I did mine. I needed to extract more than 25k machines from a security group.
$Groups = gc C:\Temp\Groups.txt
$results = foreach ($Group in $Groups) {
Get-ADGroup $Group -Properties Member | Select-Object -ExpandProperty Member | Get-ADObject -Properties Name
}
$results | Export-csv "C:\Temp\Groups.csv" -NoTypeInformation
This will give you all of the members of a group quickly (mine had 85k members)
$groupMembers = Get-ADGroup -Identity $group -Server $domainGroupIsIn -Properties Member | Select-Object -ExpandProperty Member ;
or if you need to filter some
$whereMatch = $recipient.DistinguishedName.Remove(0, $index); # limits to a domain or container
$groupMembers = Get-ADGroup -Identity $group -Server $domainGroupIsIn -Properties Member | Select-Object -ExpandProperty Member | Where {$_ -match $whereMatch};
Just increase the limit from ADUC --> View --> Filter Option - Maximum number of options displayed per folder.
That's it. Try again running your command. It takes me 4 days to figure out this and finally it's working.
I am trying to pull groups in from a text file and one of my groups is too large, 80,000 people.
How do I get this to work l, it outputs how I want it.
$groups = Get-Content c:\temp\ADGroups.txt
foreach($group in $groups) {
#(Get-ADGroup $group -Properties Member| Select-Object -ExpandProperty Member).Count
Get-ADGroupMember -Identity $group |
Get-ADObject -Properties Name, DisplayName |
Select-Object -Property #{n="Username";e={$_.Name}}, DisplayName,
#{n="AD Group";e={$group}} |
Export-Csv C:\Users\Desktop\GroupsInfo.CSV -NoTypeInformation -Append
}
The number of objects that Get-ADGroupMember can return is restricted by a limit in the ADWS (Active Directory Web Services):
MaxGroupOrMemberEntries
5000
Specifies the maximum number of group members (recursive or non-recursive), group memberships, and authorization groups that can be retrieved by the Active Directory module Get-ADGroupMember, Get-ADPrincipalGroupMembership, and Get-ADAccountAuthorizationGroup cmdlets. Set this parameter to a higher value if you anticipate these cmdlets to return more than 5000 results in your environment.
According to this thread you should be able to work around it by querying group objects and expanding their member property (if you can't increase the limit on the service):
Get-ADGroup $group -Properties Member |
Select-Object -Expand Member |
Get-ADUser -Property Name, DisplayName
Beware, though, that this is likely to be slow, because you'll be sending thousands of requests. It might be better to build a hashtable of all users:
$users = #{}
Get-ADUser -Filter '*' -Property Name, DisplayName | ForEach-Object {
$users[$_.DistinguishedName] = $_
}
so that you can look them up by their distinguished name:
Get-ADGroup $group -Properties Member |
Select-Object -Expand Member |
ForEach-Object { $users[$_] }
I was hitting the 5000 limit with Get-ADGroupMember.
You can use Get-ADUser with the -LDAPFilter parameter to get group members. It's quick and supports >5000 entries.
$groups = #(
"group1"
"group2"
"group3"
)
Foreach ($group in $groups) {
Get-ADUser -LDAPFilter "(&(objectCategory=user)(memberof=CN=$group,OU=Groups,OU=rest,DC=of,DC=distinguished,DC=name))" | Export-Csv "C:\$group.csv"
}
It looks like you can build up complex filters with this method. I needed to quickly return enabled members from some extremely large groups. The filter I used for this was:
"(&(objectCategory=user)(!useraccountcontrol:1.2.840.113556.1.4.803:=2)(memberof=CN=$group,OU=Groups,OU=rest,DC=of,DC=distinguished,DC=name))"
I hear this is a limitation of the AD Webservices that actually service the requests from powershell cmdlets. The maximum size is 5000. But you can try the dsget command, although you will need to get a little creative.
$GroupDN = (Get-ADGroup -Identity $Group).DistinguishedName will give you the DN of the group.
Use the DSget like this.
$members = DSget group $GroupDN -members This will give you the list of DNs of all members.
Feed that to a Get-ADUser cmdlet in a pipe or foreach loop and you are good to go.
You would need to use the -resultpagesize parameter. The highest value you can specify is 2147483647.
So:
Get-ADGroupMember -Identity $group -resultpagesize 2147483647 |
Select-Object -Property #{n="Username";e={$_.Name}}, DisplayName,
#{n="AD Group";e={$group}} |
Export-Csv C:\Users\Desktop\GroupsInfo.CSV -NoTypeInformation -Append
This is how I did mine. I needed to extract more than 25k machines from a security group.
$Groups = gc C:\Temp\Groups.txt
$results = foreach ($Group in $Groups) {
Get-ADGroup $Group -Properties Member | Select-Object -ExpandProperty Member | Get-ADObject -Properties Name
}
$results | Export-csv "C:\Temp\Groups.csv" -NoTypeInformation
This will give you all of the members of a group quickly (mine had 85k members)
$groupMembers = Get-ADGroup -Identity $group -Server $domainGroupIsIn -Properties Member | Select-Object -ExpandProperty Member ;
or if you need to filter some
$whereMatch = $recipient.DistinguishedName.Remove(0, $index); # limits to a domain or container
$groupMembers = Get-ADGroup -Identity $group -Server $domainGroupIsIn -Properties Member | Select-Object -ExpandProperty Member | Where {$_ -match $whereMatch};
Just increase the limit from ADUC --> View --> Filter Option - Maximum number of options displayed per folder.
That's it. Try again running your command. It takes me 4 days to figure out this and finally it's working.
I'm trying to query Active Directory to get a list of all users and all groups each user is a member of. I only need the direct groups each user is a member of, not the nested groups. The end-goal is to output this list to a CSV file. I'm attempting to do this using PowerShell in Windows Server 2012 R2.
UPDATE
So I've now managed to output a list of all users' names, however only some of the users's groups are included in the output, using the following command:
Get-ADuser -LDAPFilter "(objectClass=user)" -property "memberOf" |
select -Property #{n='name';e={$_.name}},#{n='groups';e
{$($_.MemberOf | Get-adgroup | % {$_.name}) -join ','}}
I'm unable to determine why only some of the users output (probably only 5-10 total) include the groups the user is a member of, while the rest (95%) of the users output only display the name of the user, without any groups at all.
Any ideas from here?
First of all I'am afraid that Get-ADuser -Filter {group -eq 'Domain Users'} just give nothing.
You can try to begin :
Get-ADuser -LDAPFilter "(objectClass=user)" -property "memberof" | select -Property #{n='name';e={$_.SamAccountName}},#{n='groups';e={$_.MemberOf -join ','}}
Then you can modify the filter to also take InetOrgPerson.
Get-ADuser -LDAPFilter "(|(objectClass=user)(objectClass=inetOrgPerson))" -property "memberof" | select -Property #{n='name';e={$_.SamAccountName}},#{n='groups';e={$_.MemberOf -join ','}}
Then you can take the samAccountName of the group DN
Get-ADuser -LDAPFilter "(|(objectClass=user)(objectClass=inetOrgPerson))" -property "memberof" | select -Property #{n='name';e={$_.SamAccountName}},#{n='groups';e={$($_.MemberOf | Get-adgroup | % {$_.SamAccountname}) -join ','}}
Late reply to this post, but I built a script that output all Groups in a specific OU and all users of each group. Only downside is that the "owner" of each group is also a member, so there is a bit of redundancy, but nothing breaking for my purpose. The output is formatted into two columns.
$mGroups=#(
Get-ADGroup -filter * -SearchBase "OU=,OU=,OU=,DC=,DC=" | select name);
$col = #()
for ($i=0
$i -lt $mGroups.Count;
$i++)
{
$agents=#(
Get-ADGroupMember $mGroups[$i].name | select sAMAccountName)
for ($n=0
$n -lt $agents.Count;
$n++)
{
$agentList = [PSCustomObject]#{
Group = $mGroups[$i].name
Agents = $agents[$n].sAMAccountName
}
$col+=$agentList;
}
}
$col
$col | Export-CSV -NoTypeInformation C:\Path\to\file.type
Is it possible to get a count of members that belong to a specific group based on the OU? When I run the code below it is giving me the value of 3 for each OU when there is only 1 OU that has a value of 3, the rest should be 0. It is running the Get-ADGroupMember -Identity “Test_Group”).count against the whole active directory structure instead of just for each OU??
import-module activedirectory
foreach ($ou in Get-ADOrganizationalUnit -filter * -SearchScope 1){
$computers = 0 + (get-adcomputer -filter * -searchbase $ou.distinguishedname).count
$ou | add-member -membertype noteproperty -name Computers -value $computers -force
Foreach ($Member in $ou){
(Get-ADGroupMember -Identity “Test_Group”).count
}
$ou | select name,computers
}
My interpetation of your question is that for a paricular AD Group you are looking for a member count based on OU or container.
Get-ADGroupMember -Identity "insert_your_group" -Recursive |
Where-Object{$_.objectClass -eq "User"} |
Get-ADUser -Properties canonicalname |
Select-Object #{Name='Container';Expression={$_.canonicalname | split-path -parent}} |
Group-Object container |
Select Name,Count
Breaking this down line by line
Grab all member of a particular group as well including members of other groups.
Ensure we are only processing users and not the group themselves. We already have all the users from the -Recursive so they can be ignored.
Get all the user objects with a Get-ADUser call. We need the canonicalname as that is we get the information for the parent container
Here is the fun part. Using the canonicalname split it up (like you would a directory) and just take the -parent portion.
Group the objects in order to get the count you are looking for
Simplify output with a select statment.
Output
Name Count
---- -----
Domain.Local\OU\SubOU 8
Domain.Local\OU\SubOU2 8
Domain.Local\OU\SubOU5 2
(Get-ADGroupMember 'AD-groupname' -Recursive).count