Get AD group members with ADSI - Powershell - powershell

I cannot use the Active Directory Module to get the SamAccountName of the users in a specific AD-group. How can I do this with ADSI?
I've tried:
$Group = [ADSI]"LDAP://DN of the AD group"
$Group.Member | ForEach-Object {
$Searcher = [adsisearcher]"(samAccountName=$_)"
$searcher.FindOne().Properties
}
But I see this message:
The samAccountName search filter is invalid.
How can I do this?

There are 2 ways around this as I see it, there might be an easier way of doing it though.
One is to search for all users which's memberOf attribute has the DistinguishedName of the group (this might be the less cumbersome approach):
$group = 'CN=myGroup, OU=myOU, DC=myDomain'
$searcher = [adsisearcher]"(&(objectclass=user)(objectcategory=person)(memberof=$group))"
$members = foreach($member in $searcher.FindAll()) {
$member.Properties.samaccountname
}
The other way around is using the same approach as you're using in your question:
$group = 'CN=myGroup, OU=myOU, DC=myDomain'
$adsi = [adsi]"LDAP://$group"
$members = foreach($member in $adsi.member) {
$isUser = [adsi]"LDAP://$member"
if('person' -in $isUser.objectclass) {
$isUser.samaccountname
}
}
Similar as the one above, but using adsisearcher, not sure which one would be more efficient in this case:
$members = foreach($member in $adsi.member) {
$check = [adsisearcher]"(&(distinguishedname=$member)(objectclass=user)(objectcategory=person))"
if($isUser = $check.FindOne()) {
$isUser.Properties.samaccountname
}
}

I ran this modified version of your code on my own system, so I could see what the search string actually looked like:
$Group = [ADSI]"LDAP://DN of the AD group"
$Group.Member | ForEach-Object {
$searchKey = "(samAccountName=$_)"
$searchKey
$Searcher = [adsisearcher]$searchKey
# $searcher.FindOne().Properties
}
Note the point where I let $searchKey come to the console. When I do this, I see values with the full distinguished name instead of just samAccountName. Based on this result I changed the code to look for that value instead of samAccountName, and then I saw (presumably) expected results:
$Group = [ADSI]"LDAP://DN of the AD group"
$Group.Member | ForEach-Object {
$Searcher = [adsisearcher]"(distinguishedName=$_)"
$searcher.FindOne().Properties
}

Related

Issue with ADSI script not pulling users from all groups

I have a list of groups that i need to pull back all users. I am aware due to the numbers it is restricted. I have tried adding page size but it does not work.
Here is the code
Get-Module ActiveDirectory - ErrorAction silentlycontinue
Function resolve-group}
param ($group)
For each ($member in $group.member){
$obj = [ADSI] ("LDAP://" + member)
if (obj.objectclass[1] -eq 'group'){resolve-group $obj}
else {
If ($obj.employeeid.length -eq 6)
{
$displayname = $obj.displayname
$employeeid = $obj.employeeid
$groupname = $group.name
$global:members +="$employeeid,$displayname,$groupname"
}
}
}
}
$global:members =#()
$group = [ADSI] "LDAP://cn=ab,ou=cd,ou=ef,DC=gh,DC=BB"
resolve-group $group
$group = [ADSI] "LDAP://cn=aa,ou=cc,ou=ef,DC=gh,DC=BB"
resolve-group $group
"ID,Name,Group" > c:\test\groups.csv
$global:members | sort-object - unique >> c:\test\groups.csv
I don't know how to amend the script to add and increase the page size?
I have only listed a couple of the groups but there are 100's of groups
Thanks

How can I speed up a query to Win32_UserAccount filtering by FullName property

I'm trying to find a specific user based on the FullName property of the user using a simple WMI command in powershell:
Get-WmiObject win32_useraccount -Filter "fullname='Jack Ryan'"
There are about 50,000 users and this is taking up to 30 seconds to find all the users based on the FullName property.
However when I try to search based on Name instead of FullName I get a response back in under a second. I don't understand why it's taking so long to lookup by FullName.
How can I speed this up? (Unfortunately I need to filter based on FullName and get all the usernames for those identities)
Getting group members via ADSI, as per #rboy comment. Probably easiest to have your own function here if you cannot use Get-LocalGroupMember.
function Get-LocalMembers {
Param(
[parameter(Mandatory=$false)][string]$GroupName
)
$ADSI = [ADSI]"WinNT://$env:COMPUTERNAME"
if ($PSBoundParameters.ContainsKey('GroupName')) {
$Groups = $ADSI.Children.Find($GroupName,'Group')
}
else {
$Groups = $ADSI.Children | Where-Object { $_.SchemaClassName -eq 'Group' }
}
Foreach ($Group in $Groups) {
[PSCustomObject] #{
Group = $($Group | Select-Object -ExpandProperty Name)
Members = $(
$Group.Invoke('members') | ForEach-Object {
$_.GetType().InvokeMember("Name",'GetProperty',$null,$_,$null)
}
)
}
}
}
Usage:
Get-LocalMembers # Get members of all groups
Get-LocalMembers -GroupName Administrators # Get members of specified group
EDIT
Getting both Name and FullName properties. I'm not sure really how much more we could do with ADSI in PowerShell here. I've never really explored it any further than user objects and group/member lists.
function Get-LocalMembers {
Param(
[parameter(Mandatory=$false)][string]$GroupName
)
$ADSI = [ADSI]"WinNT://$env:COMPUTERNAME"
if ($PSBoundParameters.ContainsKey('GroupName')) {
$Groups = $ADSI.Children.Find($GroupName,'Group')
}
else {
$Groups = $ADSI.Children | Where-Object { $_.SchemaClassName -eq 'Group' }
}
Foreach ($Group in $Groups) {
[PSCustomObject] #{
Group = $($Group | Select-Object -ExpandProperty Name)
Members = $(
$Group.Invoke('members') | ForEach-Object {
[PSCustomObject] #{
Name = $_.GetType().InvokeMember("Name",'GetProperty',$null,$_,$null)
FullName = $(
# A Group can be a member of a group and doesn't have a 'FullName property'
Try {
$_.GetType().InvokeMember("Fullname",'GetProperty',$null,$_,$null)
}
Catch {
"Group"
}
)
}
}
)
}
}
}
Disclaimer: I'm running this on a local, non-domain joined laptop none of my accounts have the Fullname property populated.

How to pass an array through Add-UnifiedGroupLinks -Identity?

I would like to add a user to several Office365 groups in one go.
My code is as follows:
$OfficeGroups = #("Egg_Group", "Chicken Group", "Soup Group")
foreach ($Group in $OfficeGroups)
{
$AddParams = #{
Identity = $Group
LinkType = 'Members'
Links = $Username
}
Add-UnifiedGroupLinks #AddParams
}
I am unable to pass an array of groups through the -Identity parameter. Is there an alternative cmdlt I could use? I have tried
Add-DistributionGroupMember
but it still doesn't work. Is this an impossible task?
When you work with an array of group names it should be sufficient to just loop through them:
$OfficeGroups = #('Egg_Group', 'Chicken_Group', 'Soup Group')
foreach ($Group in $OfficeGroups) {
$AddParams = #{
Identity = $Group
LinkType = 'Members'
Links = $Username
}
Add-UnifiedGroupLinks #AddParams
}
Note: It's always better to use splatting i.e. a hashtable to feed parameters to your function if you want to make it look more readable.
Can you try looping through your array like this?
$OfficeGroups = #("Egg_Group", "Chicken Group", "Soup Group")
$OfficeGroups | ForEach-Object {Add-UnifiedGroupLinks -Identity $_ -LinkType 'Members' -Links $Username}

Getting AD Group Membership ADSI using PowerShell

I currently have ADSI code to get the groups a user is a part of:
$searcher = [adsisearcher]"(samaccountname=$env:USERNAME)"
$searcher.FindOne().Properties.memberof
$adgroups = $User -Replace '^cn=([^,]+).+$', '$1'
However, i am wanting to be able to choose a group and see its members. I currently have this code to get their DN and path.
$Group = [ADSI]"LDAP://cn=Test,cn=Test,dc=some,dc=domain,dc=net"
$Members = $Group.Member | ForEach-Object {[ADSI]"LDAP://$_"}
I am wanting to get other attributes if possible (name, etc.). Any help would be appreciated as i have been trying for a bit.
You already have both pieces, the first piece is finding the users in the group, the second piece is using the searcher to get properties for the users. Just use distinguishedname as the [adsisearcher] filter.
$Group = [ADSI]"LDAP://cn=Test,cn=Test,dc=some,dc=domain,dc=net"
$Group.Member | ForEach-Object {
$Searcher = [adsisearcher]"(distinguishedname=$_)"
$searcher.FindOne().Properties
}

Using Powershell to remove a user from a list of groups

Trying to get this script to remove a user from a list of groups.
Not sure what part of my language here is wrong. It doesn't return an error in ISE. I'm admittedly a rookie in writing my own powershell scripts instead of modifying others. Any help is appreciated.
Import-Module ActiveDirectory
$group = #('grouopname1','groupname2','groupname3')
$user = "testa"
if ($user.Memberof -like $group)
{
foreach ($user in $group )
{
Remove-ADPrincipalGroupMembership -identity $user -MemberOf $group -confirm:$False
}
}
On thing you'll need to learn when using PowerShell is that it's very important to test what kind of output and object will give you.
$user = "testa" | $user.MemberOf
That will give you an error, because a string doesn't have a member property "MemberOf"
$user = Get-ADUser testa -Properties MemberOf
That will give you an object containing the user "testa", and since the MemberOf property isn't retrieved by default, you will need to add it in.
$user.MemberOf
This will return the DistinguishedName of all groups that the user is a member of, but it will not get nested groups... that would require more logic, but you can find that if you search for it.
Your group array would work... if you do a replace on $user.MemberOf so that it only returns the Common Name, but you can easily just compare the DNs. To do that however, you would need to do something like this:
$groups = $group | foreach ($g in $group) { Get-ADGroup $g }
Not pretty, but it will get you there.
The final part of the loop can be something like this:
foreach ($u in ($user.MemberOf))
{
if (($groups.DistinguishedName) -Contains $u)
{
Do-Whatever
}
}
I would generally start with a test inside the loop, using Write-Host or -WhatIf to verify just what was going to be done.