I use a script to export users with a determinates GG groups in active directory but I want to do the opposite, I mean I want to export users that are not members of that groups. I attached the part of the code that I do now:
$Group = 'GG_LCS_UsersType4'
$Users = Get-ADGroupMember $Group -Recursive -Server $Domain |
Get-ADUser |
select SamAccountName, Enabled |
Export-Csv Temp.csv -NoTypeInformation -Encoding UTF8
Import-Csv Temp.csv |
Select-Object *, @{Name='Group';Expression={"$Group"}},
@{Name='Domain';Expression={"$Domain"}} |
Export-Csv "${Domain}_LicenseControlReport.csv" -NoTypeInformation -Encoding UTF8 -Append
So now I want users that are not members of 'GG_LCS_UsersType4', 'GG_LCS_UsersType3', 'GG_LCS_UsersType2', 'GG_LCS_UsersType1'
Depending on how dynamic you want your code to be, there are a number of ways to approach this question.
Scenario 1 (Users Not in a Single Group):
$group = 'GG_LCS_UsersType4'
$groupDN = (Get-ADGroup $group).DistinguishedName
$users = (Get-ADUser -filter {objectclass -eq "user"} -properties memberof).where{$_.memberof -notcontains $groupDN}
$users | Select-Object SamAccountName,Enabled |
Export-Csv Temp.csv -NoTypeInformation -Encoding UTF8
Scenario 2 (Users Not in Multiple Groups):
$groups = 'GG_LCS_UsersType4', 'GG_LCS_UsersType3', 'GG_LCS_UsersType2', 'GG_LCS_UsersType1'
$whereFilter = $groups | Foreach-Object {
$g = (Get-ADGroup $_).DistinguishedName
"{0} '{1}'" -f '$_.memberOf -notcontains',$g
}
$whereFilter = [scriptblock]::Create($whereFilter -join " -and ")
$users = (Get-ADUser -filter {objectclass -eq "user"} -properties memberof).where($whereFilter)
$users | Select-Object SamAccountName,Enabled |
Export-Csv Temp.csv -NoTypeInformation -Encoding UTF8
Scenario 1 queries for the Distinguished Name of the group and stores that result in $groupDN
. Get-ADUser
is used to query all AD users and then the result is filtered to output users who do not have the group Distinguished Name in the .MemberOf
attribute. The .where()
method is used with the -notcontains
operator for the post-query filtering.
Scenario 2 loops through multiple groups and creates an array of strings that will be used later in the .where()
method. The strings are created using the format operator (-f
) even though concatenation would look prettier in this case. Each array entry simply contains $_.memberOf -notcontains <Group Distinguished Name>
. The entries are joined by an -and
operator and then converted to a ScriptBlock, which is represented by $whereFilter
. Since the .where()
method accepts a ScriptBlock type as a parameter, we can simply just pass $whereFilter
.
$Users
contains the user objects returned from the queries. I've selected the properties that you provided in your question, but this could easily be tweaked for whatever properties you want.
In all honestly, it may just be easier to query all AD users. Then do your specific filtering from the all AD users query. The main reason the search isn't simpler besides the lack of robust commands in the ActiveDirectory module is that you are searching for an array of values within an array. Checking for single values in an array is much simpler and PowerShell can natively handle those types of queries among most of the Collection object types.