I am trying to make a script that will add and remove computers from a group if they are in a specific ou. What I have so far adds the computers and then when run again it removes all computers from the group. Then run it again and it adds them all back.
It should add the computers that are in the OUs and remove the computers that have been moved out of the OU
$OUSTUCOMPUTERS = "OU=STUDENT,OU=Computers,DC=domain,DC=local"
$OUConstruction = 'BCT','Carpentry','Electrical Occupations','HVAC'
$List = #{}
$Group=[ADSI]"LDAP://CN=CompStuConstruction,OU=Computer Groups,OU=Computers,DC=domain,DC=local"
foreach ($Shop in $OUConstruction)}
{$Distinguishedname = "OU="+"$Shop"+","+"$OUSTUCOMPUTERS"
$OU = [ADSI]"LDAP://$distinguishedname"
# Enumerate all objects in the OU.
$arrChildren = $OU.Children
ForEach ($Child In $arrChildren)
{
# Only consider computer objects.
If ($Child.Class -eq "computer")
{
# Add all computers in the OU to the hash table.
$List.Add($Child.distinguishedName, $True)
# Check if user a member of the group.
If ($Group.IsMember($Child.ADsPath) -eq $False)
{
# Add the computers to the group.
$Group.Add($Child.ADsPath)
"Added " + $Child.distinguishedName
}
}
}
}
# Enumerate all members of the group.
ForEach ($Member in $Group.member)
{
# Check if this member object is a computer object in the OU.
If ($List.ContainsKey($Member)-eq $False)
{
# Remove this member from the group.
$Group.Remove("LDAP://$Member")
"Removed " + $Member
}
}
I would suggest to use the ActiveDirectory module instead of [ADSI]. Then do
# get your group
$group = Get-ADGroup -Identity "your group"
# clear group
Remove-ADGroupMember -Identity $group -Members #(Get-ADGroupMember -Identity $group)
# add back only correct computer objects
Add-ADGroupMember -Identity $group -Members #(Get-AdComputer -Filter * -SearchBase "your ou" -SearchScope Subtree)
Related
I am working on a solution that will help keep our Active Directory clean, so I want to use a Powershell script that will remove the disabled accounts from all groups.
I got the following script:
foreach ($username in (Get-ADUser -SearchBase "OU=Terminated Users,DC=corp,DC=company,DC=com" -filter *)) {
# Get all group memberships
$groups = get-adprincipalgroupmembership $username;
# Loop through each group
foreach ($group in $groups) {
# Exclude Domain Users group
if ($group.name -ne "domain users") {
# Remove user from group
remove-adgroupmember -Identity $group.name -Member $username.SamAccountName -Confirm:$false;
# Write progress to screen
write-host "removed" $username "from" $group.name;
# Define and save group names into filename in c:\temp
$grouplogfile = "c:\temp\" + $username.SamAccountName + ".txt";
$group.name >> $grouplogfile
}
}
}
It's working fine but only for security groups. Users are not deleted from distribution groups. I searched the Internet and people mostly suggest to use "Remove DistributionGroup Member" cmdlet. However, this is the Exchange cmdlet and we use Google Workspace for our email, so this cmdlet is not recognized when I run it on the DC.
Any idea how to solve it? Thanks!
The cmdlet Remove-ADPrincipalGroupMembership will help:
#get all disabled users in specified OU
$disabledUsers = get-aduser -SearchBase "OU=test_piotr,DC=corp,DC=company,DC=com" -LDAPFilter '(userAccountControl:1.2.840.113556.1.4.803:=2)' -Properties memberof,samaccountname
#Loop through array and remove groupmembership and store operation result in $result
$result = #(
foreach ($user in $disabledusers){
try {
#Only process user account if memberships are present
If ($user.memberof){
#Remove all memberships the user has currently, no need to exclude domain users as $user.memberof does not return it
$null = Remove-ADPrincipalGroupMembership -Identity $user.samaccountname -MemberOf $user.memberof -Confirm:$false -ErrorAction:stop
write-host "Removed user: $($user.samaccountname) from groups: $($user.memberof -join ',')"
#Build object for logfile, you could also loop through $user.memberof to create one object per removed group
$attrsHt = #{
smaccountname=$user.samaccountname
group=($user.memberof -join ',')
status='removed'
exception=$null
}
New-Object -typename psobject -Property $attrht
}
}
Catch {
write-error "Failed to remove user: $($user.samaccountname) from groups: $($user.memberof -join ',') - Exception: $_"
$attrsHt = #{
smaccountname=$user.samaccountname
group=($user.memberof -join ',')
status='error'
exception=$_
}
New-Object -typename psobject -Property $attrht
}
}
)
Using powershell I must check on each Administrator user that they are only a member of a particular group and not of other groups.
Of course since the Active Directory.
I have an order that allows me to make a list of accounts that are related to the group, but it doesn’t work:
$users = Get-QADUser ""nom du compte""
$group = Get-QADGroupMember ""nom du group""
$members = Get-QADGroupMember -Identity $group | Select -ExpandProperty Name
ForEach ($user in $users) {
If ($members -contains $user) {
Write-Host "$user exists in the group"
} Else {
Write-Host "$user not exists in the group"
}}
I'm looking to check current user group membership and run the script based on that. This script runs. However, it requires RSAT Active Directory tools to run.
I would like to run this script as a GPO. Does anyone have any ideas?
Thanks in advance.
###########################################################################################
# Check AD group Membership
###########################################################################################
$user = "$env:UserName"
$groups = 'FM-TMASQLUserAccess'
foreach ($group in $groups) {
$members = Get-ADGroupMember -server **servernamehere** -Identity $group -
Recursive | Select -ExpandProperty SamAccountName
If ($members -contains $user) {
Write-Output "$user is a member of $group"
}
Else {
Write-Output "$user is not a member of $group"
}
}
For the current logged in user, specifically, you don't need to explicitly query AD - the users security token already contains all the group memberships resolved at logon, so you can do:
$groupName = 'FM-TMASQLUserAccess'
# Fetch identity information about current user
$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent()
# Grab group SIDs from the users token
$groupTokenSIDs = $currentUser.Groups
# Translate the SID references to account/group names
$Groups = $groupTokenSIDs |Where-Object { $_.AccountDomainSid } |ForEach-Object { $_.Translate([System.Security.Principal.NTAccount]) }
# Test if list contains target group
if($Groups |Where-Object { $_.Value -like "*\$groupName" }){
"$env:USERNAME is a member of $groupName"
}
I am trying to get a script to run that checks if User within an OU and added to the same named Security Group,
If the user moves to another OU it needs to be removed from the group and added to the new group
I understand the concept of what I need to do but I cannot get it into PowerShell.
The User will move from OU to OU, and will need to be removed from the current group and added to the New group
OU's and Security Groups are named the Same:
OU Structure is
You need to use the Compare-object cmdlet.
Try this on some Test OUs and Test user accounts to be safe:
(Update the variables in the beginning of the script to match your environment...)
$VerbosePreference = "continue"
$UserOULocation = "OU=Test unit,OU=OU1,DC=Domain,DC=local" # please update
$DCServerName = "<servername>" # please update
$ADUsers = Get-ADUser -SearchBase $UserOULocation -filter * -Properties * -Server $DCServerName
$OUNames = Get-ADOrganizationalUnit -SearchBase $UserOULocation -Filter *
Foreach ($ADUser in $ADUsers)
{
$Groups = $ADUser.MemberOf | % {Get-ADGroup $_}
$CurrentOU = $ADUser.distinguishedname.Split(",")[1].replace("OU=","")
If ($Groups)
{
# You need to comapre the list of OUs to the groups that the account is a member of
$Comparing = Compare-Object $CurrentOU $Groups.name
foreach ($compare in $Comparing | Where-Object {$OUNames.name -contains $_.inputobject})
{
If ($Compare.SideIndicator -eq "<=")
{
$GroupName = $Compare.InputObject
Write-Verbose "Adding user $($aduser.name) to group $GroupName"
Add-ADGroupMember -Identity $Compare.InputObject -Members $ADUser.SamAccountName -Verbose
}
else
{
$GroupName = $Compare.InputObject
Write-Verbose "Removing user $($aduser.name) from group $GroupName "
Remove-ADGroupMember -Identity $GroupName -Members $ADUser.SamAccountName -Verbose
}
}
}
else
{
Write-Verbose "No - No groups found for user $($aduser.name)"
Write-Verbose "ACTION - Adding user to groups"
Add-ADGroupMember $CurrentOU -Members $ADUser.samaccountname
}
}
If this question is about you wanting to move user 'X' to another OU and by doing so:
remove him from the group with the same name as the OU he is in currently
add him to the group with the same name as the OU he is moved to
Then you could do something like this:
# change these to match your configuration
$userToMove = 'jdoe'
$destinationOU = 'OU=Accounting,DC=Europe,DC=Fabrikam,DC=com'
$user = Get-ADUser -Filter "SamAccountName -eq '$userToMove'" -ErrorAction -SilentlyContinue
if (!$user) { Write-Warning "User '$userToMove' does not exist" }
else {
# parse the OU from the users DistinguishedName property
$currentOU = [regex]::Match($user.DistinguishedName, '(?i)(?=OU=).*$').Value
# use the OU names to get the names for the groups
$currentGroup = (Get-ADOrganizationalUnit -Identity $currentOU).Name
$newGroup = (Get-ADOrganizationalUnit -Identity $destinationOU).Name
# if you need the DisplayNames instead,add parameter -Properties DisplayName
# and get the DisplayName property value. ie:
# $currentGroup = (Get-ADOrganizationalUnit -Identity $currentOU -Properties DisplayName).DisplayName
# $newGroup = (Get-ADOrganizationalUnit -Identity $destinationOU -Properties DisplayName).DisplayName
# remove the user from the group with the same name as the OU he's currently in
Remove-ADGroupMember -Identity $currentGroup -Members $user
# add the user to the new group
Add-ADGroupMember -Identity $newGroup -Members $user
# finally move the user to the new OU
$user | Move-ADObject -TargetPath $destinationOU
}
Regex details used in parsing the OU from the users DistinguishedName:
(?= Assert that the regex below can be matched, starting at this position (positive lookahead)
OU= Match the characters “OU=” literally
)
. Match any single character that is not a line break character
* Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
$ Assert position at the end of the string (or before the line break at the end of the string, if any)
I have a list of accounts (SAM account names) and a list of groups all the accounts need to be removed from. My problem is that I have to specify -server DC01 since the users are in a different domain. I can do that for removing 1 user at a time with:
$Groups = Get-Content C:\temp\groups.txt
$user = get-aduser <username> -Server "DC01.domain.com"
foreach ($Group in $Groups) {
Write-Host "Removing $user from $group" -Foreground Yellow
Remove-ADGroupMember -Identity $group -Members $user -Confirm:$false
}
But I have several long lists of users, and there's got to be a way to do this for all of them.
I tried adding the ** entries below, but no dice:
$Groups = Get-Content C:\temp\groups.txt
$user = Get-Content C:\temp\users0.txt **-Server "DC01.domain.com"**
foreach ($Group in $Groups) {
Write-Host "Removing $user from $group" -Foreground Yellow
Remove-ADGroupMember -Identity $group -Members $user **-searchbase = "DC=domain,DC=com"** -Confirm:$false
}
Thanks in advance for any suggestions!
I cannot test this right now, but I believe you can set the -Members parameter to an array of users.
Apparently, the Remove-ADGroupMember does not work if you supply an array of DistinguishedNames when the users are from another domain, so we need to use the full default (Microsoft.ActiveDirectory.Management.ADUser) objects as returned by the Get-ADUser cmdlet.
$DCGroups = (Get-ADDomain your.domainA.com).PDCEmulator # get a PDC emulator in domain A where the groups are
$DCUsers = (Get-ADDomain your.domainB.com).PDCEmulator # get a PDC emulator in domain B where the users are
$Groups = Get-Content 'C:\temp\groups.txt' # the groups are in domainA
# get an array users ADUser Objects from Domain B
$users = Get-Content 'C:\temp\users0.txt' | ForEach-Object {
$user = Get-ADUser -Filter "SamAccountName -eq '$_'" -Server $DCUsers -ErrorAction SilentlyContinue
if ($user) { $user }
}
# remove these users from the groups in Domain A
foreach ($Group in $Groups) {
Write-Host "Removing $($users.Count) users from $Group" -Foreground Yellow
Remove-ADGroupMember -Identity $Group -Members $users -Confirm:$false -Server $DCGroups
}
Edit
To overcome the exception being thrown when you try to remove a user that is not a member of the group, you need to add some extra code to make sure the -Members parameter of Remove-ADGroupMember contains only ADUser objects that currently are member of this group.
$DCGroups = (Get-ADDomain your.domainA.com).PDCEmulator # get a PDC emulator in domain A where the groups are
$DCUsers = (Get-ADDomain your.domainB.com).PDCEmulator # get a PDC emulator in domain B where the users are
$Groups = Get-Content 'C:\temp\groups.txt' # the groups are in domainA
# get an array users ADUser Objects from Domain B
$users = Get-Content 'C:\temp\users0.txt' | ForEach-Object {
$user = Get-ADUser -Filter "SamAccountName -eq '$_'" -Server $DCUsers -ErrorAction SilentlyContinue
if ($user) { $user }
}
# remove these users from the groups in Domain A
foreach ($Group in $Groups) {
# get a list of SamAccountNames of users that are currently a member of this group
$members = Get-ADGroupMember -Identity $Group | Where-Object {$_.objectClass -eq 'user'} | Select-Object -ExpandProperty SamAccountName
# create a subset of users that are indeed in the members list
$removeThese = #($users | Where-Object { $members -contains $_.SamAccountName })
if ($removeThese.Count) {
Write-Host "Removing $($removeThese.Count) users from $Group" -Foreground Yellow
Remove-ADGroupMember -Identity $Group -Members $removeThese -Confirm:$false -Server $DCGroups
}
else {
Write-Host "No users need to be removed from group '$Group' " -Foreground Green
}
}