Powershell list group names for each user in array - powershell

I want to return the group names in a semicolon delimited list for each AD user in an array. Here is what I have so far:
$ADuser = Get-ADUser -filter * -Properties * | ? {$_.employeeNumber -eq " 9408" -or $_.employeeNumber -eq "3816"} | Select-Object Name,SamAccountName,UserPrincipalName,DisplayName,GivenName,Surname,description,mail,Enabled,HomeDirectory,distinguishedname,MemberOf
foreach($user in $ADuser)
{
$Groups = forEach ($group in $ADuser.memberOf)
{
(Get-ADGroup $group).name
}
$groupStr = $Groups -join ";"
$ADuser = $ADuser | Select-Object Name,SamAccountName,UserPrincipalName,DisplayName,GivenName,surname,description,mail,Enabled,HomeDirectory,distinguishedname,#{n='Groups';e={$groupStr}}
}
This code works fine when $ADuser contains a single user. When $ADuser contains more than one user, I get the following error each time it tries to set Groups:
Get-ADGroup : Cannot validate argument on parameter 'Identity'. The argument is null. Provide a valid value for the argument, and then try running the command again.
At line:8 char:22
+ (Get-ADGroup $group).name
+ ~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-ADGroup],
ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADGroup
I expect the output to be like this for each $ADuser:
Name : John.Doe
SamAccountName : John.Doe
UserPrincipalName : John.Doe#mydomain.com
DisplayName : John Doe
GivenName : John
Surname : Doe
description : Joe is a person
mail : John.Doe#mydomain.com
Enabled : True
HomeDirectory : \\fileserver\homefolders\John.Doe
distinguishedname : CN=John.Doe,OU=People,OU=my,DC=domain
Groups : Group1;Group2;Group3;Group4

Looks like you have messed up with these two variables: $ADUsers and $users.
$ADuser = Get-ADUser -filter * -Properties * | ? {$_.employeeNumber -eq " 9408" -or $_.employeeNumber -eq "3816"} | Select-Object Name,SamAccountName,UserPrincipalName,DisplayName,GivenName,Surname,description,mail,Enabled,HomeDirectory,distinguishedname,MemberOf,Groups
$Results = New-Object System.Collections.ArrayList
foreach($user in #($ADuser))
{
$Groups = forEach ($group in #($user.memberOf))
{
(Get-ADGroup $group).name
}
$user.Groups = $Groups -join ';'
[Void]$Results.Add($user)
}
$Results

Kirill Pashkov's helpful answer solves your immediate problem.
To take a step back:
Your symptoms suggest that you're running on PSv2, which has the following implications:
Member-access enumeration (PSv3+) isn't available; that is, if $ADuser is an array (a collection), you cannot use .memberOf to implicitly collect the .memberOf property values of its elements.
A foreach (...) { ... } loop executes its loop body even if the value to enumerate is $null - in PSv3+ the loop body isn't executed at all.
That said, your code can presumably be reduced to this one command:
Get-ADUser -Properties * |
? {$_.employeeNumber -eq " 9408" -or $_.employeeNumber -eq "3816"} |
Select-Object Name,
SamAccountName,
UserPrincipalName,
DisplayName,
GivenName,
Surname,
description,
mail,
Enabled,
HomeDirectory,
distinguishedname,
#{
n='Groups';
e={ ($_.memberOf | Get-AdGroup | Select-Object -ExpandProperty Name) -join ";" }
}

Related

Powershell variable issue Get-Content and Get-ADGroup

I'm trying to figure out the reason why I can run the script using variable $groups with Get-Content but it wont work if variable $groups goes with Get-ADGroup list I did below...
Block that works:
$groups = Get-Content C:\groups.csv
$results = #()
$file = "C:\Usuarios_Grupos_Darwin_AD.csv"
foreach($Group in $Groups) {
$results +=Get-ADGroupMember -Id $Group -Recursive | %{Get-ADUser -Identity $_.SamAccountName -Properties Enabled,Name} | Select #{Expression={$Group};Label=”Group Name”},SamAccountName,Name,Enabled
}
$results | export-csv -notypeinformation -Delimiter ";" -path $file
Block that's not working:
(only the first line has been changed)
$groups = Get-ADGroup -Filter {Name -like '*Darwin*'} -Properties * | select -property Name
$results = #()
$file = "C:\Usuarios_Grupos_Darwin_AD.csv"
foreach($Group in $Groups) {
$results +=Get-ADGroupMember -Id $Group -Recursive | %{Get-ADUser -Identity $_.SamAccountName -Properties Enabled,Name} | Select #{Expression={$Group};Label=”Group Name”},SamAccountName,Name,Enabled
}
$results | export-csv -notypeinformation -Delimiter ";" -path $file
Here is the error:
Get-ADGroupMember : Cannot bind parameter 'Identity'. Cannot create object of type "Microsoft.ActiveDirectory.Management.ADGroup". The adapter cannot set the value of property
"Name".
At line:11 char:34
+ $results +=Get-ADGroupMember -Id $Group -Recursive | %{Get-ADUser -Id ...
+ ~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-ADGroupMember], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember
I'm trying to embed the output list all in one script without having to generate csv with another script.
Thanks in advance !!
A few notes about your code:
the -Filter parameter should be a string, not a scriptblock
using $results += is very costly because the entire array needs to be rebuilt in memory on each addition
Get-ADGroupMember can return also computer and (when not used with -Recursive) also group objects, not just users, so you cannot pipe directly to Get-ADUser
never use -Properties * if all you want is one single property
Try this:
# Get-ADGroup already returns objects with these properties:
# DistinguishedName, GroupCategory, GroupScope, Name, ObjectClass, ObjectGUID, SamAccountName, SID
$groups = Get-ADGroup -Filter "Name -like '*Darwin*'"
$file = "C:\Usuarios_Grupos_Darwin_AD.csv"
# let PowerShell collect the objects for you instead of using +=
$results = foreach($Group in $Groups) {
# Get-ADGroupMember can return objects of type users and computers (also groups when used without -Recursive)
# so filter the result to get only user objects
$Group | Get-ADGroupMember -Recursive | Where-Object { $_.objectClass -eq 'user' } | ForEach-Object {
$_ | Get-ADUser | Select #{Name = 'Group Name'; Expression={$Group.Name}}, SamAccountName, Name, Enabled
}
}
$results | Export-Csv -Path $file -NoTypeInformation -Delimiter ";"

Getting AD groups and their users

I've been trying to get a list of all the groups in our AD environment (with the description) and their members and output it to a CSV file. Ideally the users would be shown under their group. The script I've been trying to use is:
Import-Module ActiveDirectory
Get-ADGroup -Filter * -Properties Description |
Select-Object Name, Description |
ForEach-Object {
Get-ADGroupMember -Identity $_.DistinguishedName -Recursive |
Get-ADObject -Properties SamAccountname, Title, Department |
Select-Object Name, SamAccountName, Title, Department, DistinguishedName, ObjectClass
} | Export-Csv -Path c:\temp\ADGrab.csv -NoTypeInformation
The error I keep getting is as follows:
Get-ADGroupMember : Cannot validate argument on parameter 'Identity'. The argument
is null or empty. Supply an argument that is not null or empty and then try the
command again.
At C:\Users\j_kennedy_ta\AppData\Local\Temp\9\2898ceb2-a6cf-4fbf-9341-e651dad2145d.ps1:4 char:28
+ Get-ADGroupMember -Identity <<<< $_.distinguishedname -Recursive |
+ CategoryInfo : InvalidData: (:) [Get-ADGroupMember], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember
Without the nasty Select-Object and with group information in the CSV file:
Import-Module ActiveDirectory
Get-ADGroup -Filter * -Properties Description |
ForEach-Object {
# Store for later use
$groupName = $_.Name
$groupDescription = $_.Description
Get-ADGroupMember -Identity $_.DistinguishedName -Recursive |
Get-ADObject -Properties SamAccountname, Title, Department |
Select-Object Name, SamAccountName, Title, Department, DistinguishedName, ObjectClass, ` # Mind the gap
# Calculated properties with group information
#{ name = "GroupName"; expression = $groupName }, `
#{ name = "GroupDescription"; expression = $groupDescription }
} | Export-Csv -Path c:\temp\ADGrab.csv -NoTypeInformation

Get-ADGroup - Group Name, ManagedBy Name and Email

I'm looking to get the the Group Name, Managed By Name and Managed by Email in a PowerShell query similar to this.
Get-ADGroup -filter {Name -like "*Admins" }
The output would look something similar to:
Group Name | Managed By Name | Managed By Email
The issue I'm having is with joining Get-ADGroup and Get-ADUser. In SQL this "join" would happen on get-adgroup.managedby = get-aduser.distinguishedname. I know that's not how it works in Powershell, just thought I'd throw out an example of what I'm trying to do.
Any help would both be welcomed and appreciated.
I see #Mathias R. Jessen beat me to it, but here's what I had:
Get-ADGroup -filter {Name -like "*IT*" } -Properties managedBy |
ForEach-Object {
$managedBy = $_.managedBy;
if ($managedBy -ne $null)
{
$manager = (get-aduser -Identity $managedBy -Properties emailAddress);
$managerName = $manager.Name;
$managerEmail = $manager.emailAddress;
}
else
{
$managerName = 'N/A';
$managerEmail = 'N/A';
}
Write-Output $_; } |
Select-Object #{n='Group Name';e={$_.Name}}, #{n='Managed By Name';e={$managerName}}, #{n='Managed By Email';e={$managerEmail}}
You can do it like this:
$Groups = Get-ADGroup -Filter { Name -like "*Admins" } -Properties managedBy,mail
$Groups |Select-Object Name,#{Name='ManagedBy';Expression={(Get-ADUser $_.managedBy).Name}},Mail
The #{} syntax after Select-Object is known as a calculated property.
You could also pipe the groups to ForEach-Object and call Get-ADUser inside the process scriptblock:
Get-ADGroup -Filter {Name -like "*Admins"} -Properties managedBy,mail |ForEach-Object {
# Find the managedBy user
$GroupManager = Get-ADUser -Identity $_.managedBy
# Create a new custom object based on the group properties + managedby user
New-Object psobject -Property #{
Name = $_.Name
ManagedBy = $GroupManager.Name
Email = $_.mail
}
}
I would something do like this:
# Get all groups into a variable
$Group = Get-ADGroup -Filter {Name -like "*Admin*"} | Select-Object -expandProperty Name
foreach ($Groups in $Group){
# Get ManagedBy name for each group (If ManagedBy is empty group wil not be listed)
$User = Get-ADGroup $Groups -Properties * | Select-Object -ExpandProperty ManagedBy
foreach ($Users in $User){
# Get Name and EmailAddress for each User
$Name = Get-ADUser $Users | Select-Object -ExpandProperty Name
$Email = Get-ADUser $Users -Properties * | Select-Object -ExpandProperty EmailAddress
# Write output
Write-Host $Groups "," $Name "," $Email
}
}
Hope this helps.

Filter Managedby Powershell

Below are my current attempts to pull AD groups whose managedby equal names like "ML...". I keep getting errors so I wanted to know why I am unable to filter managedby with "-like" when I can filter managedby "-eq $..." variables. I tried making a variable $name = "ML*" so that I can perform {managedby -eq $name} but still had no luck.
I mostly get error like:
Operator(s): The following: ''Eq', 'Ne'' are the only operator(s) suppor
ted for searching on extended attribute: 'ManagedBy'.
and so forth because "-eq" is only accepted for some filters I have done. When I use -eq I get these errors:
Import-Module : The following error occurred while loading the extended type dat
a file:
Microsoft.PowerShell, C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\ActiveD
irectory\ActiveDirectory.Types.ps1xml : File skipped because it was already pres
ent from "Microsoft.PowerShell".
Microsoft.PowerShell, C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\ActiveD
irectory\ActiveDirectory.Types.ps1xml : File skipped because it was already pres
ent from "Microsoft.PowerShell".
At J:\\ManagedbyEqualsML.ps1:1 char:14
+ Import-Module <<<< ActiveDirectory
+ CategoryInfo : InvalidOperation: (:) [Import-Module], RuntimeExc
eption
+ FullyQualifiedErrorId : FormatXmlUpateException,Microsoft.PowerShell.Comm
ands.ImportModuleCommand
The term 'Get-adgroup' is not recognized as the name of a cmdlet, function, scri
pt file, or operable program. Check the spelling of the name, or if a path was i
ncluded, verify that the path is correct and try again.
At J:\\ManagedbyEqualsML.ps1:53 char:27
+ $MLgroupAll = Get-adgroup <<<< -Properties managedby, enabled, name -filter
{managedby -eq $name}
+ CategoryInfo : ObjectNotFound: (Get-adgroup:String) [], CommandN
otFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Here are my codes where I attempted to find Owners that have the name ML*
Import-Module ActiveDirectory
$name = "ML*"
#Attempt 1
$MLgroups = Get-adgroup -Properties managedby, enabled, name -filter * | Select name, managedby
foreach ($group in $MLgroups){
if ($group.managedby -like "ML*"){
write-host $group.name + $group.managedby}
}
#Attempt 2
$Mgroups = get-adgroup -Properties name, managedby -filter *
foreach ($groups in $Mgroups){
# here get the group name and use the "managedBy attribute to retrieve the user object
# grou naem
$gname = $_.Name
$manager=Get-AdUser $_.ManagedBy
$MangerName = $manager.DisplayName
if ($managerName -like "ML*"){
write-host $gname + $managerName}
}
#Attempt 3
$exportlist = "C:\Temp\managedby.txt"
Clear-Content $exportlist
$Header = `
"Group ID Name" + "|" + "ManagedBy"
$Header | Out-File $exportlist -Append
$list = get-adgroup -properties name, managedby -filter {managedby -like "ML_*"} `
| Select name, managedby | Export-CSV $exportlist -NoType -Delimiter '|'
#Attempt 4
$MLgroupAll = Get-adgroup -Properties managedby, enabled, name -filter {managedby -like $name}
foreach ($group in $MLgroupAll) {
write-host $group.name + $group.managedby}
UPDATE: if i try to changed my $name variable it still doesn't work and gives another error.
$MLgroupAll = get-adgroup -Properties managedby, enabled, name -filter {managedby -eq $name}
foreach ($group in $MLgroupAll) {
$managed = $group.managedby
if ($managed -like "ML*"){
write-host $group.name + $group.managedby }
}
ERROR:
Get-ADGroup : Identity info provided in the extended attribute: 'ManagedBy' coul
d not be resolved. Reason: 'Cannot find an object with identity: 'ML*' under: 'D
C=we,DC=dirsrv,DC=com'.'.
#Paul: here is my error still:
Here is an example that works for me (orienting myself at your last try):
get-adgroup -filter * -Properties managedby | % {
if($_.managedby -like "CN=ML*"){
write-host $_.name + $_.managedby
}
}

Powershell - Get Last Logon

I have a quick script I am trying to reuse from getting computers lastlogon. Due to time constraints I am posting it here for assistance. I am trying to use the display name and even tried using the sam, but no luck.
$results = #()
$CompanyUsers = import-csv c:\bin\users.csv
foreach ($i in $CompanyUsers)
{
$results += Get-Aduser -Filter $i.sam -Properties * | select Name, Lastlogondate
#$results += Get-Aduser -Filter {displayname -eq $i.displayname} -Properties * | select Name, Lastlogondate
}
$results | export-csv c:\bin\Userslogon.csv
I get syntax errors. I can manually put in the values so I am thinking it has to do with data types extracted from the array. Suggestions would be appreciated!
SAM ERROR:
Get-Aduser : Error parsing query: 'xxx001' Error Message: 'syntax error' at position: '1'.
At C:\bin\Get-UserLastLogon.ps1:19 char:14
+ $results += Get-Aduser -Filter $i.sam -Properties * | select Name, Lastlogondat ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Get-ADUser], ADFilterParsingException
+ FullyQualifiedErrorId : Error parsing query: 'kal001' Error Message: 'syntax error' at posi
tion: '1'.,Microsoft.ActiveDirectory.Management.Commands.GetADUser
DISPLAYNAME ERROR:
Get-Aduser : Property: 'displayname' not found in object of type:
'System.Management.Automation.PSCustomObject'.
At C:\bin\Get-UserLastLogon.ps1:20 char:17
+ $results += Get-Aduser -Filter {displayname -eq $i.displayname} -Properties ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-ADUser], ArgumentException
+ FullyQualifiedErrorId : Property: 'displayname' not found in object of type: 'System.Manage
ment.Automation.PSCustomObject'.,Microsoft.ActiveDirectory.Management.Commands.GetADUser
Thanks for the suggestions. I found a way to get this to work:
# Create array of users
$results = #()
$Users = Get-Content C:\bin\fullnames.txt
# Get last logon date
foreach($i in $Users)
{
$results += Get-ADUser -ldapfilter "(displayname=$i)" -Property * | Select-Object -Property name, samaccountname, lastlogondate
}
# Export results to csv file
$results | export-csv c:\bin\logonusers.csv
Try one of these:
Get-Aduser -Filter "samaccountname -eq '$i.sam'" -Properties *
Get-Aduser -Filter "displayname -eq '$i.displayname'" -Properties *
The samaccountname will be faster, since that's an indexed property.
# Create array of users
$results = #()
$Users = Get-Content C:\bin\fullnames.txt
# Get last logon date
foreach($i in $Users)
{
$results += Get-ADUser -ldapfilter "(displayname=$i)" -Property * | Select-Object -Property name, samaccountname, lastlogondate
}
# Export results to csv file
$results | export-csv c:\bin\logonusers.csv