Create one report from two separate collections - powershell

I am missing something fundamental in PowerShell.
I have a script that generates two collections, computer names with version details of a specific application and a separate user name list that is taken from the computer names list because the user names are in the computer names, for example a computer name is:
XXXXXX02jbloggs
The owner of this computer is jbloggs and jbloggs is a valid AD object which has a full name of joe blogs.
The ultimate objective of the script is to produce a report with computer names, owner SamAccountName, full name and application details, which the script will specifically check for.
For example,
what version(s) of Adobe Reader exist on this range of machines
So far I have:
$ErrorActionPreference = "SilentlyContinue"
$Computers = Get-ADComputer -Server BlahBlah.com -Filter {name -like "XXXXXX02*"} |
Select-Object -ExpandProperty Name
$Users = $Computers -Replace '\D*\d*(\w*)', '$1'
$Results = foreach ($Computer in $Computers) {
Get-CimInstance -ComputerName $Computer -ClassName Win32_Product |
Where-Object{$_.Name -like "*Adobe Reader*"} |
Select-Object PSComputerName, Name, Version, InstallDate
}
$FullNames = ForEach ($user in $Users) {
Get-ADUser -Server BlahBlah.com -Identity $User -Properties * |
Select-Object -ExpandProperty Name
}
$Results gets me a list of computer names, Adobe Reader xxx, the version and install date.
$FullNames gets me a list of the full names based on their user IDs
I do not know how to construct the script so it produces Full Name, User Name, Computer Name, Application Name and Install Date.
This is why I say I am missing something fundamental in PowerShell, I have been looking at custom objects, nested loops and other ideas but to no avail. Really looking for some advice on this type of problem as I several similar examples I need to accomplish.
Any advice would be greatly appreciated.

Get the single current user inside the foreach($computer in $Computers) instead of creating two separate foreach.
Add a calculated property to the select to include FullName in
$Result
$ErrorActionPreference = "SilentlyContinue"
$Computers = Get-ADComputer -Server BlahBlah.com -Filter {name -like "XXXXXX02*"} |
Select-Object -ExpandProperty Name
$Results = foreach ($Computer in $Computers) {
$User = $Computer -Replace '\D*\d*(\w*)', '$1'
$FullName = (Get-ADUser -Server BlahBlah.com -Identity $User -Properties *).Name
Get-CimInstance -ComputerName $Computer -ClassName Win32_Product |
Where-Object{$_.Name -like "*Adobe Reader*"} |
Select-Object PSComputerName, Name, Version, InstallDate,#{n='FullName';e=#{$FullName}}
}

Related

Get entries of a file from a filtered list

I am trying to grab the host file entries of servers in mulptiple OUs here to show the host file entries and server names
$OUpath =
'OU=Sales,OU=Servers,OU=_Production,OU=Upgraded,DC=fabrikam,DC=local'
'OU=DCHR,OU=Servers,OU=_Production,OU=Upgraded,DC=fabrikam,DC=local'
'OU=Finance,OU=Servers,OU=Test,OU=Upgraded,DC=fabrikam,DC=local'
$ExportPath = 'c:\servers.csv'
$OUpath | Foreach {
Get-ADComputer -Filter * -SearchBase $OUpath} | Select-object DistinguishedName,DNSHostName,Name,Description | Export-Csv -NoType $ExportPath
Part A up ran fine...How can i get the entries of the results. I am tending towards content but hope to have it all in one script. Any help would be nice.
An alternative to #FoxDeploy's helpful answer, here is how you can do the same using the pipelines with ForEach-Object.
Note that Description is not a default property for Get-ADComputer you will need to add -Properties Description to see it's value.
Another point to consider, by default, if you don't specify the -SearchScope, Get-ADComputer will perform a SubTree search, meaning that it will bring all computers of the specified OU and all computers on all the OUs contained in the Base OU. If you just want to bring the computers in the OU without going down in recursion, you should add -SearchScope OneLevel.
#(
'OU=Sales,OU=Servers,OU=_Production,OU=Upgraded,DC=fabrikam,DC=local'
'OU=DCHR,OU=Servers,OU=_Production,OU=Upgraded,DC=fabrikam,DC=local'
'OU=Finance,OU=Servers,OU=Test,OU=Upgraded,DC=fabrikam,DC=local'
) | ForEach-Object {
Get-ADComputer -Filter * -SearchBase $_ -Properties Description
} | Select-Object DistinguishedName,DNSHostName,Name,Description |
Export-Csv 'c:\servers.csv' -NoTypeInformation
I think the primary issues were the array getting declared incorrectly, and incorrect syntax for the ForEach-Object cmdlet
$OUpath = #(
'OU=Sales,OU=Servers,OU=_Production,OU=Upgraded,DC=fabrikam,DC=local'
'OU=DCHR,OU=Servers,OU=_Production,OU=Upgraded,DC=fabrikam,DC=local'
'OU=Finance,OU=Servers,OU=Test,OU=Upgraded,DC=fabrikam,DC=local'
)
$ExportPath = 'c:\servers.csv'
$OUpath |
ForEach-Object {
Get-ADComputer -Filter * -SearchBase $_ -Properties Description
} |
Select-Object DistinguishedName, DNSHostName, Name, Description |
Export-Csv $ExportPath -NoTypeInformation
You have to use $_ in this context where you were using $OUpath previously. Select-Object can take the the piped output from the ForEach-Object loop rather than being in the loop, which should be more efficient. Likewise for Export-Csv.
As implied by FoxDeply's very good answer that might signal an attempt to use A ForEach(...) loop construct instead of ForEach-Object. But if we are going that route I think it's slightly better to let PowerShell populate the array for us.
$OUpath = #(
'OU=Sales,OU=Servers,OU=_Production,OU=Upgraded,DC=fabrikam,DC=local'
'OU=DCHR,OU=Servers,OU=_Production,OU=Upgraded,DC=fabrikam,DC=local'
'OU=Finance,OU=Servers,OU=Test,OU=Upgraded,DC=fabrikam,DC=local'
)
$Servers =
ForEach( $Path in $OUpath )
{
Get-ADComputer -Filter * -SearchBase $path -Properties Description |
Select-Object DistinguishedName, DNSHostName, Name, Description
}
$Servers | Export-Csv $ExportPath -NoTypeInformation
Alternatively you could skip the Select-Object inside the loop and add $Servers = $Servers | Select-Object ... right after the loop. Although the difference is probably negligible.
With some minor restructuring, this should get you past your issue
$OUpath = (
'OU=Sales,OU=Servers,OU=_Production,OU=Upgraded,DC=fabrikam,DC=local',
'OU=DCHR,OU=Servers,OU=_Production,OU=Upgraded,DC=fabrikam,DC=local',
'OU=Finance,OU=Servers,OU=Test,OU=Upgraded,DC=fabrikam,DC=local')
$ExportPath = 'c:\servers.csv'
$servers = new-object System.Collections.ArrayList
ForEach($path in $OUpath){
$ouServers = Get-ADComputer -Filter * -SearchBase $path | Select-object DistinguishedName,DNSHostName,Name,Description
$servers.AddRange($ouServers) | Out-Null
}
"found $($servers.Count) servers!"
$servers | export-csv $exportPath
I made the list of OU Paths a PowerShell array, then iterate through them using the standalone ForEach loop. Then commit the items to a variable that will persist ($servers) and output the CSV.

Get membership for list of computers

I have been using the following command to pull the list of membership for a given machinename:
Get-ADPrincipalGroupMembership -Identity (Get-ADComputer <MACHINENAME>)
| select-object name | Out-File C:\mydir\MemberShip.csv
The membership identifies software associated to a machine such as Adobe Acrobat Pro, MS Project, etc. Sometimes the software is associated but not actually installed which is why I use the query to validate this information against another list. I am trying to run a query to pull the membership for a list of assets in a text file and export with the name of each computer and the membership for each as well. Maybe get it to display something like the following:
NAME NAME
----------- -------------
<MACHINENAME1> ADOBE ACROBAT PRO
MS PROJECT STD
MS VISIO PRO
<MACHINENAME2> ADOBE ACROBAT PRO
ADOBE PHOTOSHOP
I have tried the following but I get a few errors:
$computers = Get-Content .\computers.txt
Get-ADPrincipalGroupMembership ForEach ($computer in $computers)
{Get-ADComputer $computer} | select-object operatingSystem, name |
Out-Gridview
Any help or guidance would be greatly appreciated. Thank you.
You could do something like this. You could put it in a script, function or whatever.
$results = New-Object -TypeName System.Collections.ArrayList
$computers = Get-Content .\computers.txt
$computers | ForEach-Object {
$ComputerObject = Get-ADComputer $_
$obj = #{
Computername = $_
OS = $ComputerObject.OperatingSystem
}
$obj.Memberships = Get-ADPrincipalGroupMembership -Identity $ComputerObject | select-object name
$results.Add($obj) | Out-Null
}
return $results
$computers = Get-Content .\computers.txt
$results = foreach ( $computer in $computers ) {
$adcomputerproperties = get-adcomputer -Identity $computer -Properties *
Get-ADPrincipalGroupMembership -Identity $adcomputerproperties.DistinguishedName
| select #{n="Computername";e={ $computer}},Name,#{n="OperatingSystem"; e={ $adcomputerproperties.OperatingSystem}} }
$results | Out-GridView

How to filter Get-ADComputer output

My Get-ADComputer script gives too much information. I would like to shorten it out a little.
$Computer = Read-Host -Prompt 'Input computer name'
$ManagedBy = Get-ADComputer $Computer -Properties ManagedBy |
foreach { $_.ManagedBy }
Write-Output $ManagedBy
When I tried to run my scrip it gives this to output
CN=Last Name First Name ,OU=XX ,OU=XXX ,OU=XXX ,DC=XXX,DC=XXX
I would like to get only CN in the output (First name and Las Name).
Your code returns the distinguished name of the computer's manager. You can use that DN to query the AD user object and obtain the desired properties from that (like FullName, or DisplayName, or the individual values FirstName and LastName).
Get-ADComputer $Computer -Properties ManagedBy |
Select-Object -Expand ManagedBy |
Get-ADUser -Property FullName |
Select-Object -Expand FullName
Firstly have you looked at the objects properties?
These Properties are auto assigned to the variable, when created.
You can see them with:
$ManagedBy | Get-Member
You may well find that $ManagedBy.Name will give exactly what you want.
Further reading for you: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-member?view=powershell-6

Powershell Adding users within groups to cross forest groups

This script works without error now, but the problem is that when several groups in the searchbase are found, the script will add all users from all groups to the cross forest target groups.
So for example:
ForestAGroup1 = contains 2 users
ForestAGroup2 = contains 2 users
::runs script::
now...
ForestBGroup1 = contains 4 users
ForestBGroup2 = contains 4 users
The ForestBGroup1/2 needs to contain the same identical users as ForestAGroup1/2.
Here is the script for reference:
$creds = Get-Credential
$Groups = Get-ADGroup -Properties * -Filter * -SearchBase "OU=TEST,OU=Shop Print Groups,OU=User,OU=domain Groups,DC=domainA,DC=com" | export-csv c:\temp\test.csv
$Groups = Get-ADGroup -Properties * -Filter * -SearchBase "OU=TEST,OU=Shop Print Groups,OU=User,OU=domain Groups,DC=domainA,DC=com"
Foreach($G In $Groups)
{
#Display group members and group name
Write-Host $G.Name
Write-Host "-------------"
$G.Members
#Add members to domainB group
$domainGMembers = import-csv C:\temp\test.csv | ForEach-Object -Process {Get-ADGroupMember -Identity $_.CN} | Select-Object samaccountname | export-csv c:\temp\gmembers.csv
$domainDNUser = import-csv C:\temp\gmembers.csv | ForEach-Object -Process {Get-ADUser $_.samaccountname -Server "domainA.com" -properties:Distinguishedname}
import-csv C:\temp\gmembers.csv | ForEach-Object -Process {Add-ADGroupMember -Server "domainB.com" -Identity $G.Name -Members $domainDNUser -Credential $creds -Verbose}
}
What are you doing?
You export to csv, but still try to save it to a variable
You search twice
You add all members from ALL groups in TEST-OU to every group in domainB
You waste time on saving and reading data that you already have in memory
You search for the user-object to get SamAccountName when you already have something ten times better, the DN. Then you use that SamAccountName to find the DN.
Try this (untested):
$creds = Get-Credential
$Groups = Get-ADGroup -Properties Members -Filter * -SearchBase "OU=TEST,OU=Shop Print Groups,OU=User,OU=domain Groups,DC=domain,DC=com"
Foreach($G In $Groups)
{
#Display group members and group name
Write-Host $G.Name
Write-Host "-------------"
$G.Members
#Add members to domainB group
$G.Members |
Get-ADUser -Server fairfieldmfg.com |
ForEach-Object { Add-ADGroupMember -Server "domainB.com" -Identity $G.Name -Members $_ -Credential $creds -Verbose }
}
I used a foreach-loop to run the Add-ADGroupMember because it usually fails in the middle of a group of members if it finds on the already is a member, but if we add them one at a time you get around that (or you could do a search and exclude those already in the group).
You may want to add -ErrorAction SilentlyContinue to Add-ADGroupMember to ignore those errors when you know the script works as it should.

How to get all groups that a user is a member of?

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?
I fixed my mistake: Get-Member should be Get-ADGroupMember.
Get-ADPrincipalGroupMembership will do this.
Get-ADPrincipalGroupMembership username | select name
name
----
Domain Users
Domain Computers
Workstation Admins
Company Users
Company Developers
AutomatedProcessingTeam
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
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
Old school way from CMD:
net user mst999 /domain
(GET-ADUSER –Identity USERNAME –Properties MemberOf | Select-Object MemberOf).MemberOf
This should provide you the details for current user. Powershell not needed.
whoami /groups
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 *
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?
Universal group is a security or distribution group that contains
users, groups, and computers from any domain in its forest as
members. You can give universal security groups rights and
permissions on resources in any domain in the forest.
Global group is a group that can be used in its own domain, in member
servers and in workstations of the domain, and in trusting domains.
In all those locations, you can give a global group rights and
permissions and the global group can become a member of local groups.
However, a global group can contain user accounts that are only from
its own domain.
Domain local group is a security or distribution group that can
contain universal groups, global groups, other domain local groups
from its own domain, and accounts from any domain in the forest. You
can give domain local security groups rights and permissions on
resources that reside only in the same domain where the domain local
group is located.
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.
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.]
Get-Member is a cmdlet for listing the members of a .NET object. This has nothing to do with user/group membership. You can get the current user's group membership like so:
PS> [System.Security.Principal.WindowsIdentity]::GetCurrent().Groups |
Format-Table -auto
BinaryLength AccountDomainSid Value
------------ ---------------- -----
28 S-1-5-21-... S-1-5-21-2229937839-1383249143-3977914998-513
12 S-1-1-0
28 S-1-5-21-... S-1-5-21-2229937839-1383249143-3977914998-1010
28 S-1-5-21-... S-1-5-21-2229937839-1383249143-3977914998-1003
16 S-1-5-32-545
...
If you need access to arbitrary users' group info then #tiagoinu suggestion of using the Quest AD cmdlets is a better way to go.
I wrote a PowerShell function called Get-ADPrincipalGroupMembershipRecursive. It accepts the DSN of a user, computer, group, or service account. It retrieves an initial list of groups from the account's memberOf attribute, then recursively checks those group's memberships. Abbreviated code is below. Full source code with comments can be found here.
function Get-ADPrincipalGroupMembershipRecursive( ) {
Param(
[string] $dsn,
[array]$groups = #()
)
$obj = Get-ADObject $dsn -Properties memberOf
foreach( $groupDsn in $obj.memberOf ) {
$tmpGrp = Get-ADObject $groupDsn -Properties memberOf
if( ($groups | where { $_.DistinguishedName -eq $groupDsn }).Count -eq 0 ) {
$groups += $tmpGrp
$groups = Get-ADPrincipalGroupMembershipRecursive $groupDsn $groups
}
}
return $groups
}
# Simple Example of how to use the function
$username = Read-Host -Prompt "Enter a username"
$groups = Get-ADPrincipalGroupMembershipRecursive (Get-ADUser $username).DistinguishedName
$groups | Sort-Object -Property name | Format-Table
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
Use:
Get-ADPrincipalGroupMembership username | select name | export-CSV username.csv
This pipes output of the command into a CSV file.
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.
It is just one line:
(get-aduser joe.bloggs -properties *).memberof
end of :)
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=$_;}} `
}
Get-QADUser -SamAccountName LoginID | % {$_.MemberOf } | Get-QADGroup | select name
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.
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.
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
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
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)
}
}
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
Import-Module ActiveDirectory
Get-ADUser -SearchBase "OU=Users,DC=domain,DC=local" -Filter * | foreach-object {
write-host "User:" $_.Name -foreground green
Get-ADPrincipalGroupMembership $_.SamAccountName | foreach-object {
write-host "Member Of:" $_.name
}
}
Change the value of -SearchBase to reflect the OU you need to list the users from :)
This will list all of the users in that OU and show you which groups they are a member of.
Get-ADPrincipalGroupMembership USERLOGON | select name
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}
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.
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
}
}
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=""; `
}