Consider it taken care of.

List all the groups a user is a member of … Thank-You PowerShell

Let me start by saying that if you still cling to vbscript (as I did for so long) I have to say come to the dark side we have cookies. Seriously things are so much better once you get it figured out.

For whatever reason I started working with arrays in this script and learned a few cool things.

Remember how hard it was to actually remove an item from an array?
$array.remove(object)
and this is done using the value of the array member so you don’t even need to know it’s address!

recall having to write whole loops to bubble sort your array? another one liner now.

[Array]::Sort([array]$ArrayName)

And perhaps my favorite in this script, how to loop through an array and see if it contains a value, again a single line.

$array -contains "value"

The other thing I do a lot in this script is work with AD objects. Search for a user find all the groups they are a member of then bind each group and check its members etc etc. Lots of good examples of how to get a handle on an AD object. took me a long time to get it right but once you do it’s easy.

$Object= [ADSI]("LDAP://"+ $x)

where $x is the distinguished name of the object…. don’t know the DN? use the searcher

The only trick now that you have the name is actually getting the AD object to work with.

$user=$result.GetDirectoryEntry()

Starting to enjoy PowerShell yet?

# for more info s@blackops.ca
#The script will prompt you for a user logon name (no domain)
#If you click cancel or don’t enter a name the script will exit
#The script will continue to prompt you until it gets a valid username.
#The script will then load all the groups the user is a member of and go through all the nested groups reporting the hierarchy and noting any groups the use is a member of more than once.
#At the end it will output a single list sorted by group name to make it easier to find a specific group.
# This is the core function it takes an array of AD groups via distinguished name and a depth field to help with spacing in the output. For each group that is a member of a previous group it will call itself with the new array and depth +1
function GroupEnnumerate ([System.Collections.ArrayList]$InputArray, [int]$Depth)
{
$spacer=""
for ($i=1;$i -le $Depth; $i++) {$spacer=$spacer + "`t"}
#the two above lines add a tab char foe each level deep to keep the output formatted
While ($InputArray.count -gt 0) #repent until the input array is empty
{
#The next line is important to make sure we have not already processed a group.
#This prevents an endless loop if a group is a member of itself either directly or indirectly
if (!($expandedgrouparray -contains $InputArray[0]))
{
$GroupName = $InputArray[0]
$expandedgrouparray.add($InputArray[0])|Out-Null #add the new group to the array of processed groups
$Group = [ADSI]("LDAP://"+ $groupname) #lookup the group in AD
$expandedgrouparraynames.add($group.name.tostring())|Out-Null #add the group friendly name to an array for the output at the end
Write-Host $spacer($Group.Name) #display the group in the output
$TempGroupArray = New-Object System.Collections.ArrayList $null #blank and init the temp array of sub groups
foreach ($x in $group.memberof) # for each sub-group do the following
{
$member = [ADSI]("LDAP://"+ $x) #lookup the memberof in AD
If ($member.SchemaClassName -eq "group") #we don't care if the member is not a group, just in case...
{
$TempGroupArray.add($x)|Out-Null #add the sub-group to a temp array to be used when calling the function for the next loop
}
}
if ($TempGroupArray.Count -gt 0) #if we found any sub-groups start checking them
{
[Array]::Sort([array]$TempGroupArray) # sort the array so he output is easier to read
GroupEnnumerate $TempGroupArray ($Depth+1) # call the function again with the temparray if sub-groups and add another tab to the output
$tempGroupArray=$null #blank out the temp array
}
$InputArray.remove($InputArray[0]) #as we process each group in the input array we need to remove it
}
else
{
#If we have already processed the group once then just report and remove it from the input array
write-Host -ForegroundColor Red $spacer([ADSI]("LDAP://"+ ($InputArray[0]))).name "- Already a member"
$InputArray.remove($InputArray[0])
}
}
}
cls
$StartGroupArray = New-Object System.Collections.ArrayList
$ExpandedGroupArray = New-Object System.Collections.ArrayList
$ExpandedGroupArrayNames = New-Object System.Collections.ArrayList
#I create the arrarys as above so I can use the .add .remove etc
$searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]'')
$user=$null
$PromptMessage="Please enter the user logon name"
#the following do loop continues until you don't enter anything or you enter a good username
do
{
$SAMAccountName=$null
$SAMAccountName = Read-Host $PromptMessage
if ($SAMAccountName) #if there was ANY input in the box
{
$searcher.Filter = "(&(objectClass=User)(samAccountName=$SAMAccountName))"
$result = $searcher.Findone() # search AD for the requested user
if ($result)
{
$user=$result.GetDirectoryEntry()
# if we find a user in ID then get the AD object to work with later
}
else
{
# if we don't find a user update the message prompt so the user knows something happened
$PromptMessage= "User " + $samaccountname + " not found - Please enter the user logon name"
}
}
else
{
exit #if there was not ANY input in the box quit the whole script
}
}
while (!$user) # until we have a valid user object in AD keep pestering the operator
$groups = $user.memberof # get a list of all the groups that this user is a member of
foreach($group in $groups)
{
#for each group that they are a member of add the group DN to the array for processing
$StartGroupArray = $startGroupArray + $group
}
Write-Host "User: " $user.displayName " " $user.sAMAccountName " is a member of:" #this is the header of the output
[Array]::Sort([array]$startGroupArray)#fort the array so the output is easier to read
GroupEnnumerate $startGroupArray 1 #initiate the top-level group check
Write-Host # space in the output
Write-Host "Complete list sorted by group name" #second output header
$ExpandedGroupArraynames | Sort-Object #sorted list of all the groups processed that the user is a member of.
Write-Host # space in the output
Write-Host "Script Complete"

if ($SAMAccountName) #if there was ANY input in the box
{
foreach ($serachDomain in $DomainDNs)
{
$searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]”LDAP://$serachDomain”)
$searcher.Filter = “(&(objectClass=User)(samAccountName=$SAMAccountName))”
$result = $searcher.Findone() # search AD for the requested user
if ($result)
{
$user=$result.GetDirectoryEntry()
# if we find a user in ID then get the AD object to work with later
}
}
If (!$user)
{
## if we don’t find a user update the message prompt so the user knows something happened
$PromptMessage= “User ” + $samaccountname + ” not found – Please enter the user logon name”
}

}
else
{
exit #if there was not ANY input in the box quit the whole script
}
}
while (!$user) # until we have a valid user object in AD keep pestering the operator

I need almost similar script in PowerShell. I’ve the current script which is written in VBScript. I am using it to fetch the AD groups for any user, but its fetching groups along with the group type and the owner of that groups.

Please see if you can help me and give me the replacement of this in PS.

Thanks in advance.

1. “ShowGroups” helps us to see what groups that a user belongs to.
The output is a CSV file stored under R:\Scripts\GetGroups\Output\ and it is opened automatically in Excel.

‘+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
‘
‘ User’s groups dump script
‘ INPUT: UserName
‘ If the User name is different from the pre-Windows 2000 logon name,
‘ you must specify the pre-Windows 2000 name
‘
‘ DEPENDANCIES: WSH5.6, Windows 2000 or greater
‘ Read access to user accounts in the specified domain
‘+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

‘*** Some base variables we’ll use later
Dim strUserName ‘String value for user logon name
Dim strADsPath ‘String value to hold the full LDAP path to the user object
Dim objRootDSE ‘LDAP object to keep connection open to the AD LDAP directory
Dim strDomainDN ‘Default Naming Contect for the domain you are logged into
Dim strUserDN ‘Distinguished Name for the user object
Dim strGroupSupport ‘Support group for the group object extensionAttribute11

If WScript.Arguments.Count 1 Then
‘Wrong number of parameters, get a name
strUserName = inputbox( “Please Enter User name (pre-2000 version):”, “User Name Input” )
Else
‘Parameter found
strUserName = WScript.Arguments(0)
End If

‘+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
‘
‘ Connect to the file we want to use
‘
‘+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

‘==========================================================================
‘Change group name to something readable
‘==========================================================================

objGname = objGroup.Get(“Name”)

‘==========================================================================
‘Get managed by and add it to a variable then change it to CN
‘==========================================================================

‘==========================================================================
‘Get group type (Security vrs Distro) and add it to a Variable objGroupType
‘==========================================================================

'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'
' Close the CSV file and open it in Excel
'
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Good catch, some of these things feel strange and difficult to get considering how simple it appears.
I have not updated the main script because I don’t have time to test right now, but the code looks good so if that’s what you need here it is.
thanks.