Powershell Bulk Remove-ADGroupMember - arrays

I am looking to carry out a bulk removal of members from multiple groups from an imported CSV file of SAMAccountName, ADGroup. I could just loop through every record in the array (of which there will be 1600 entries) but it would be better if I could collate all of the users that are in a particular group and issue the Remove-ADGroupMember with multiple users.
I'm not sure how to process the data in the array so it appears as ADGroup, MultipleSAMAccountNames - I'm probably missing something obvious.
Example CSV:
SAMAccountName, ADGroup
User1, GroupA
User2, GroupA
User3, GroupB
User4, GroupA
Example Code:
Import-Module ActiveDirectory
$Users = Import-CSV "Users.csv"
foreach ($User in $Users)
{
Remove-ADGroupMember -identity $User.ADGroup -Members $User.SAMAccountName
}
Desired:
foreach ($Group in $Users)
{
Remove-ADGroupMember -identity $Group.ADGroup -Members $Group.MultipleSAMAccountNames
}
Thanks in advance

Try this:
$Users = Import-CSV "Users.csv"
$Groups = $Users.ADGroup | Sort-Object -Unique
foreach ($Group in $Groups) {
Remove-ADGroupMember -identity $Group -Members ($Users | Where-Object { $_.ADGroup -eq $Group }).SamAccountName
}
Gets a unique list of the groups in the CSV.
Loops through each unique group and uses Where-Object to filter $Users for any users that match that group, the result of which is then sent to the -Members parameter.
Note this is untested code, so use with care.

Mark Wragg beat me to it, but here's my (also untested) solution without the need for a Where-Object clause:
Import-Module ActiveDirectory
# read the CSV file and group the objects by the 'ADGroup' property
$UsersAndGroups = Import-CSV "Users.csv" | Group-Object -Property ADGroup
# loop through the groups
foreach ($group in $UsersAndGroups) {
# get an array of users belonging to this group
$accounts = $group.Group | Select-Object -ExpandProperty SAMAccountName -Unique
# remove them all from the group
Remove-ADGroupMember -Identity $group.Name -Members $accounts
}
For testing purposes, add the -WhatIf switch at the end of the Remove-ADGroupMember command.

Related

PowerShell array iteration or parsing problem?

I'm new to PowerShell. I'm trying to pull a users Active Directory info based on their job title and place it in a csv file. I have two corresponding arrays, $title and $csvfile. $title[0] corresponds with $csvfile[0] and $title[1] to $csvfile[1] and so on. This loop creates all my .csv files but doesn't pull any user data. I can manually enter any of the $title items into the script and it works but when used as an array I get nothing.
Does an array add any leading or ending spaces, quotations, delimiters, anything that might keep the -and statement from working?
$title = #(
'Director of Nursing'
'Assistant Director of Nursing'
'Activities Director'
)
$csvfile = #(
'DON'
'ADON'
'ACTIVITIES'
)
for($i=0; $i -lt $title.Count; $i++)
{
#Get-ADUser -Filter { (Title -like "Director of Nursing") -and (Company -like "location1") }| Export-Csv c:\temp\$($csvfile[$i]).csv"
Get-ADUser -filter { (Title -like "$($title[$i])") -and (Company -like "Location1") }| Export-Csv "c:\tempPath\$($csvfile[$i]).csv"
}
The AD module re-parses the -Filter block (and turns it into a proper LDAP filter), the likeliest explanation is that it can't resolve $($title[$i]) when that happens.
Try with a string filter instead:
Get-ADUser -filter "Title -like '$($title[$i])' -and Company -like 'Location1'"| ...

Azure ad - Powershell - remove user from group a if they are a member of group b

Hello IT Professionals,
I need some help, I am trying to create some powershell script that will check if a user is a member group B and then if they are remove them from group A - Im still very new to powershell and scripting so i am having a little trouble and wondering if I could get some assistance !
Here is what i have so far and i all I can do is list the members of group B
Get-AzureADGroupMember -ObjectId "90e136ce-f573-4b4f9990-21a314963de2"
# Get all members of the GroupB.
Foreach ($ObjectId In Get-AzureADGroupMember -ObjectId "90e136ce-f573-4b4f-9990-21a314963de2")
{
If ((Get-AzureADGroupMember -ObjectId "746e5b45-9368-434c-bab1-5d5b7baea075" -Contains $ObjectId))
{
# Remove that user from GroupA
Remove-AzureADGroupMember -ObjectId "746e5b45-9368-434c-bab1-5d5b7baea075" -Members $ObjectId
}
}
I have found some powershell scripts but im having trouble making them work for azure ad
# Get all members of the GroupB.
Foreach ($User In Get-ADGroupMember -Identity "Group B")
{
# If they are a 'MemberOf' GroupA
If ((Get-ADUser $User.SamAccountName -Properties MemberOf).MemberOf -Contains "Group A")
{
# Remove that user from GroupA
Remove-ADGroupMember -Identity "Group A" -Members $User.SamAccountName
}
}
I fully apreciate any assistance with this!
The below is the snippet.
If you are doing it for a single User :
$user_upn = "<USER UPN>"
$users= Get-AzureADGroupMember -ObjectId "<GROUP B ID>" -All $true
#Finds for a specific user and if it exists, goes ahead and remove the specific user from the Group A
$users |?{$_.UserPrincipalName -eq $user_upn} | %{Remove-AzureADGroupMember -ObjectId "<GROUP A ID>" -MemberId $_.objectid}
Explanation
Gets all the member of Group B and stores it in the variable $users.
Checks(Filters) whether the required member is present in the $users variable, if Yes, goes ahead and removes from the Group A.
If you are looking to do it for the list of UPNs from a File. You could refer to the below snippet.
#Getting the list of UPNS of the users for whom the process specified needs to be carried out
$user_upns = Get-Content "C:\ListUPN.txt"
#Iterates through each UPN
foreach( $user_upn in $user_upns)
{
Write-Host "Working on the $user_upn" -ForegroundColor Green
#Gets all user from the GROUP B
$users= Get-AzureADGroupMember -ObjectId "<GROUP B ID>" -All $true
#Finds for a specific user and if it exists, goes ahead and remove the specific user from the Group A
$users |?{$_.UserPrincipalName -eq $user_upn} | %{Remove-AzureADGroupMember -ObjectId "<GROUP A ID>" -MemberId $_.objectid}
}
This was Answered for me on another forum https://www.reddit.com/r/AZURE/comments/k910l4/azure_ad_powershell_help_user_group_memberships/
Kudos to TheStig1293 on reddit
#Store the groups in a variable
$GroupA = Get-AzureADGroupMember -ObjectId '746e5b45-9368-434c-bab1-5d5b7baea075'
$GroupB = Get-AzureADGroupMember -ObjectId '90e136ce-f573-4b4f-9990-21a314963de2'
#Using Compare-object to compare the members of the groups and then using Where-object to select the ones that are in both Groups. This is stored in a variable called Dif
$diff = Compare-Object -ReferenceObject $GroupB.ObjectID -DifferenceObject $GroupA.ObjectID -IncludeEqual | Where-Object {$_.SideIndicator -eq "=="}
#Using foreach to go through each user in diff and then removing them. We are referencing the InputObject property as the Object ID because if you look at the output of Compare-object, that is the anchor for the comparison.
foreach($user in $diff){
#I Included this so you can verify manually they are the users you would like to remove prior to removing.
#Get-AzureADUser -ObjectId $user.InputObject
Remove-AzureADGroupMember -ObjectID '746e5b45-9368-434c-bab1-5d5b7baea075' -MemberID ($User).InputObject
}

How to add users to AD group and delete some specific user files based on first letters username with Powershell

hope someone could help, I'm unfortunatelly not a Powershell expert
This is what I want:
look up users in the AD within specific OUs, based on first letter(s) of username.
Validate if they are member of a AD group, and if not;
delete some specific profile files of the user AND
add the user to that specific group.
Some part of the code I tried:
Import-Module ActiveDirectory
# OUs needed to be searched for users
$OU1 = 'name of first OU'
$OU2 = 'name of 2nd OU'
$OU3 = 'name of 3rd OU'
# AD group where users needs to be added
$Group = 'name of group'
# Ask for 1st letter of username
$usernameletter = Read-Host -Prompt 'First letter(s) username'
# Create an array with corresponding users
$userslist= #()
$users1 = Get-ADUser -Filter "SamAccountName -like '$usernameletter*'" -SearchBase $OU1 | select -ExpandProperty samAccountName
$users2 = Get-ADUser -Filter "SamAccountName -like '$usernameletter*'" -SearchBase $OU2 | select -ExpandProperty samAccountName
$users3 = Get-ADUser -Filter "SamAccountName -like '$usernameletter*'" -SearchBase $OU3 | select -ExpandProperty samAccountName
$userslist += $users1,$users2,$users3
# check membership of group
$members = Get-ADGroupMember -Identity $Group -Recursive | Select -ExpandProperty sAMAccountName
# Delete userpref files of user when user is not member of the -name of group-
foreach ($user in $userslist)
{
If ($members -contains $user)
{
Write-host "$user exists in group, so userpref files won't be deleted"
}
Else
{
#if users doesn't exist in AD Group - delete userpref files of user
Write-host "$user doesn't exist in group, deleting userpref files of user"
Remove-Item -Path E:\users\$user\pwrmenu\UserPref\{F5BE2CE1-BF67-44E2-B5B3-5E081344A70E}* -Force
}
}
# check if user is part of the group. if not, add it to the group
foreach ($user in $userslist)
{
If ($members -contains $user)
{
Write-host "$user exists in group, so user won't be added to group $group"
}
Else
{
#if users doesn't exist in AD Group - add them to AD Group
Write-host "$user doesn't exist in group, adding user to group $group"
Add-ADGroupMember $Group -Members $userslist
}
}
#end of script
for some reason the $userslist array is filled, but the foreach loop $user in $userslist doesn't work, $user is not filled in and it get errors like
Remove-Item : Cannot find path 'E:\users\pwrmenu\UserPref' because it does not exist.
Add-ADGroupMember : Cannot validate argument on parameter 'Members'. The argument is null, empty, or an element of the argument collection contains a null value.
Hope that someone could help me! thanks!
Edit
#Andrew Ryan Davis,
sorry, not very familiar with this website yet
contents of $userslist:
PS C:\Users\serverw> $userslist
WGoossensTest
wgoossenstest2
contents of $members:
PS C:\Users\serverw> $members
username1
username2
username3
etc
Not sure why you wouldn't have anything populated in user. I do see you have quite a bit of duplicated code as well as several chances for optimization. If you keep the users as an object with a samaccountname property, you can speed up your where clause by not invoking a scriptblock.
$userslist | where samaccountname -notin $members
or
$userslist | where $members -notcontains samaccountname
You also check each user against the list of group members twice. Check out the optimized version below.
Import-Module ActiveDirectory
# OUs needed to be searched for users
$OUs = 'name of first OU','name of 2nd OU','name of 3rd OU'
# AD group where users needs to be added
$Group = 'name of group'
# Ask for 1st letter of username
$usernameletter = Read-Host -Prompt 'First letter(s) username'
# Create an array with corresponding users
$userslist = $ous | foreach {
Get-ADUser -Filter "SamAccountName -like '$usernameletter*'" -SearchBase $_ | select samaccountname
}
# Get member list of group
$members = Get-ADGroupMember -Identity $Group -Recursive | Select -ExpandProperty sAMAccountName
# Delete userpref files of user when user is not member of the -name of group- and then add to the group
foreach($user in $userslist | where samaccountname -notin $members | select -ExpandProperty sAMAccountName)
{
Write-host "$user doesn't exist in group, deleting userpref files of user"
Remove-Item -Path E:\users\$user\pwrmenu\UserPref\{F5BE2CE1-BF67-44E2-B5B3-5E081344A70E}* -WhatIf
Write-host "$user doesn't exist in group, adding user to group $group"
Add-ADGroupMember $Group -Members $user -whatif
}
#end of script
This does not provide feedback of users in the group. If you really want to see that then you can split them up and run each separately.
Import-Module ActiveDirectory
# OUs needed to be searched for users
$OUs = 'name of first OU','name of 2nd OU','name of 3rd OU'
# AD group where users needs to be added
$Group = 'name of group'
# Ask for 1st letter of username
$usernameletter = Read-Host -Prompt 'First letter(s) username'
# Create an array with corresponding users
$userslist = $ous | foreach {
Get-ADUser -Filter "SamAccountName -like '$usernameletter*'" -SearchBase $_ | select samaccountname
}
# Get member list of group
$members = Get-ADGroupMember -Identity $Group -Recursive | Select -ExpandProperty sAMAccountName
$notmembersof,$membersof = $userslist.where({$_.samaccountname -notin $members},'split')
# Delete userpref files of user when user is not member of the -name of group- and then add to the group
foreach($user in $notmembersof.sAMAccountName)
{
Write-host "$user doesn't exist in group, deleting userpref files of user"
Remove-Item -Path E:\users\$user\pwrmenu\UserPref\{F5BE2CE1-BF67-44E2-B5B3-5E081344A70E}* -WhatIf
Write-host "$user doesn't exist in group, adding user to group $group"
Add-ADGroupMember $Group -Members $user -whatif
}
foreach($user in $membersof.sAMAccountName)
{
Write-host "$user exists in group, so userpref files won't be deleted"
Write-host "$user exists in group, so user won't be added to group $group"
}
#end of script
Another issue you may have already ran into is your Add-ADGroupMember targets the entire $userslist instead of each $user. I added -WhatIf so you can triple check what's going to happen before completing.
Edit
If $userlist may be empty then we should do a check, something like.
if($null -eq $userlist){write-host "userlist is empty";break}
The error in your comment shows that $userlist was empty, try these tests.
$members = 'test'
$userlist = 'test'
$match,$nomatch = $userlist.where({$_ -in $members},'split')
$members = 'test1'
$userlist = 'test'
$match,$nomatch = $userlist.where({$_ -in $members},'split')
Neither will error and in the first $match will be populated and $nomatch will be empty. In the second the opposite will be true. In neither case will it error like the one you saw.

Powershell loop deal with multiple AD users in output

I have constructed below to show an certain active directory users details and all their groups.
This works ok if only one user is returned howver if multiple users are returned I get an error with this section: "Get-ADPrincipalGroupMembership $user.samaccountname | select name"
I've looked in the direction of for loops but haven't yet found a solution
I need each user found displayed with their groups.
I plan to use this script to quickly gather info to troubleshoot user issues.
Thanks for reading
add-pssnapin quest.activeroles.admanagement
import-module activedirectory
clear-host
$name = read-host 'Whats the name ?'
$user = Get-qAduser $name -properties *
$user | select name,SamAccountName,AccountIsLockedOut,PasswordStatus,PasswordLastSet,PasswordExpires,email,ParentContainerDN,CreationDate | format-list
Get-ADPrincipalGroupMembership $user.samaccountname | select name
cmd /c pause | Out-Null
Just assume you're getting a list back and then use a foreach to iterate over the list:
add-pssnapin quest.activeroles.admanagement
import-module activedirectory
clear-host
$name = read-host 'Whats the name ?'
$users = Get-qAduser $name -properties *
foreach ($user in $users) {
$user | select name,SamAccountName,AccountIsLockedOut,PasswordStatus,PasswordLastSet,PasswordExpires,email,ParentContainerDN,CreationDate | format-list
Get-ADPrincipalGroupMembership $user.samaccountname | select name
}

i have array of users how to find what ones are Disabled

What i am trying to do = Return all Disabled accounts in certin Groups and store them in a Veriable i can use to search with VM view to detach Persistant Drives from disabled users.
$groups = Get-ADGroup -Filter {Name -like "view_*"}
$rtn = #()
ForEach ($Group in $Groups)
{
$rtn += (Get-ADGroupMember -Identity "$($group.name)" -recursive)
}
$dis = #()
foreach ($user in $rtn)
{
$dis += (get-aduser -filter {enabled -eq $false})
}
i belive this works for me but i need to know is there a Better way to do this? cause this takes a lot of time with couple thousand users
If there's any overlap in your group membership (users in multiple groups), you'll be calling Get-ADUser multiple times for the same user. This will slow you down and return duplicate data you'll have to filter out.
You can do this without the Foreach loop and array building, just a single pipeline will work. Linebreaks added for formatting clarity.
$rtn = get-adgroup -filter {name -like "view__*"}|`
foreach-object {Get-ADGroupMember $_ -recursive}|`
select-object -expandproperty distinguishedname -unique|`
get-aduser -Properties enabled|`
where-object {$_.enabled -eq $false};
This returned 37 distinct users across 9 groups. Across multiple runs, the execution time was anywhere from 1.1 to 2.5 seconds.
The method in your answer returned 60 users across those same 9 groups - with a lot of duplicates (because they weren't filtered out). Across multiple runs, the execution time was anywhere from 1.7 to 3.5 seconds.
This is feel is the best way to accomplish what i set out to do
$groups = Get-ADGroup -Filter {Name -like "view_*"}
$rtn = #()
ForEach ($Group in $Groups)
{
$rtn += (Get-ADGroupMember -Identity "$($group.name)" -recursive | %{Get-ADUser -Identity $_.distinguishedName -Properties Enabled | ?{$_.Enabled -eq $false}} )
}
if any one has a better way of doing this please let me know.

Resources