Skip to content

Commit 50a20ea

Browse files
committed
Update
1 parent 28ce04b commit 50a20ea

File tree

3 files changed

+337
-0
lines changed

3 files changed

+337
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
#requires -modules ActiveDirectory
2+
<#
3+
.SYNOPSIS
4+
Clean out disabled user accounts from a selected AD Group
5+
.DESCRIPTION
6+
This script provides a GUI to quickly clean an existing AD group from disabled user accounts, optionally recursive
7+
.PARAMETER <Parameter_Name>
8+
None
9+
.INPUTS
10+
AD Domain, Source AD group, Recursive
11+
.OUTPUTS
12+
CSVFile with cleaned out users
13+
.NOTES
14+
Version: 1.0
15+
Author: Bart Jacobs - @Cloudsparkle
16+
Creation Date: 30/09/2020
17+
Purpose/Change: Clean AD group of disabled user accounts
18+
.EXAMPLE
19+
None
20+
#>
21+
22+
#Custom function to get Recursive AD Group Members
23+
function Get-ADGroupMemberRecursive
24+
{
25+
[CmdletBinding()]
26+
param
27+
(
28+
[parameter(Mandatory = $true )]
29+
[string]$Identity,
30+
[string]$Server
31+
)
32+
33+
$RecMembers = Get-ADGroupMember -Identity $Identity -Server $Server
34+
35+
foreach($RecMember in $RecMembers)
36+
{
37+
$RecMember
38+
39+
if( $RecMember.objectClass -eq 'group' )
40+
{
41+
Get-ADGroupMemberRecursive -Identity $RecMember.SID -Server $Server
42+
}
43+
}
44+
}
45+
46+
#Making sure we can have those fancy messageboxes working...
47+
Add-Type -AssemblyName PresentationFramework
48+
49+
#Check for running as administrator, if not: exit
50+
Write-Host "Checking for elevated permissions..."
51+
if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
52+
{
53+
[System.Windows.MessageBox]::Show("Insufficient permissions to run this script. Open the PowerShell console as an administrator and run this script again.","Error","OK","Error")
54+
exit 1
55+
}
56+
else
57+
{
58+
Write-Host "Code is running as administrator — go on executing the script..." -ForegroundColor Green
59+
}
60+
61+
#Initialize variables
62+
$SelectedDomain = ""
63+
$ADGroup = ""
64+
$Subgroupname = ""
65+
$ToCleanGroup = ""
66+
$CSVFile = "c:\temp\DisabledAccountsCleaned.csv"
67+
$csvContents = @() # Create the empty array that will eventually be the CSV file
68+
69+
#Get the AD DomainName
70+
$ADForestInfo = Get-ADForest
71+
$SelectedDomain = $ADForestInfo.Domains | Out-GridView -Title "Select AD Domain" -OutputMode Single
72+
73+
#Check for a valid DomainName
74+
if ($SelectedDomain -eq $null)
75+
{
76+
[System.Windows.MessageBox]::Show("AD Domain not selected","Error","OK","Error")
77+
exit 1
78+
}
79+
80+
#Find the right AD Domain Controller
81+
$dc = Get-ADDomainController -DomainName $SelectedDomain -Discover -NextClosestSite
82+
83+
#Get all groups and select the group to clean
84+
$ADGroupList = Get-ADGroup -filter * -Server $SelectedDomain | sort name | select Name
85+
$ADGroup = $ADGroupList | Out-GridView -Title "Select the AD Group that needs cleaning" -OutputMode Single
86+
87+
#Basic checks for selecte groups
88+
if ($ADGroup -eq $null)
89+
{
90+
[System.Windows.MessageBox]::Show("Source group not selected","Error","OK","Error")
91+
exit 1
92+
}
93+
94+
#Ask for
95+
$DoRecursive = [System.Windows.MessageBox]::Show('Do you want to clean subgroups too?','Run recursive?','YesNo','Question')
96+
97+
#Fetch all members from selecte source group
98+
if ($DoRecursive -eq "Yes")
99+
{
100+
#write-host "Recursive Mode"
101+
$members = Get-ADGroupMemberRecursive -Identity $ADGroup.Name -Server $dc.HostName[0]
102+
}
103+
Else
104+
{
105+
#write-host "Non-Recursive Mode"
106+
$members = Get-ADGroupMember -Identity $ADGroup.Name -Server $dc.HostName[0]
107+
}
108+
109+
#Try to clean the selected AD Group
110+
Try
111+
{
112+
foreach ($member in $members)
113+
{
114+
If ($member.objectClass -eq "group")
115+
{
116+
$Subgroupname = $member.SamAccountName
117+
}
118+
Else
119+
{
120+
$ADUSer = get-aduser -Identity $member
121+
if ($ADUSer.Enabled -eq $False)
122+
{
123+
if ($Subgroupname -eq "")
124+
{
125+
$ToCleanGroup = $ADGroup.Name
126+
}
127+
Else
128+
{
129+
$ToCleanGroup = $Subgroupname
130+
}
131+
132+
#uncomment below for rolling output
133+
#write-host $member.SamAccountName, $ToCleanGroup
134+
Remove-ADGroupMember -Identity $ToCleanGroup -Members $member.samaccountname -Confirm:$False
135+
136+
#Get the CSV data ready
137+
$row = New-Object System.Object # Create an object to append to the array
138+
$row | Add-Member -MemberType NoteProperty -Name "Account" -Value $member.SamAccountName
139+
$row | Add-Member -MemberType NoteProperty -Name "GroupName" -Value $ToCleanGroup
140+
141+
$csvContents += $row # append the new data to the array#
142+
}
143+
}
144+
}
145+
146+
#Write the CSV output
147+
$csvContents | Export-CSV -path $CSVFile -NoTypeInformation
148+
149+
$message = "The AD Group " + $ADGroup.name + " has been cleaned."
150+
[System.Windows.MessageBox]::Show($message,"Finished","OK","Asterisk")
151+
152+
}
153+
Catch
154+
{
155+
[System.Windows.MessageBox]::Show("AD Group cleaning failed","Error","OK","Error")
156+
exit 1
157+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#requires -modules ActiveDirectory
2+
<#
3+
.SYNOPSIS
4+
Copy AD group members from one AD group to another AD group in the same domain
5+
.DESCRIPTION
6+
This script provides a GUI to quickly copy AD group members to another existing group in the same domain. Multi-domain forests are supported, the script will query for the AD domain.
7+
.PARAMETER <Parameter_Name>
8+
None
9+
.INPUTS
10+
AD Domain, Source AD group, Destination AD Group
11+
.OUTPUTS
12+
None
13+
.NOTES
14+
Version: 1.1
15+
Author: Bart Jacobs - @Cloudsparkle
16+
Creation Date: 09/03/2020
17+
Purpose/Change: Copy AD Group members to another group
18+
19+
.EXAMPLE
20+
None
21+
#>
22+
23+
#Initialize variables
24+
$SelectedDomain = ""
25+
$SourceGroup = ""
26+
$DestinationGroup = ""
27+
28+
Add-Type -AssemblyName PresentationFramework
29+
30+
#Get the AD DomainName
31+
$ADForestInfo = Get-ADForest
32+
$SelectedDomain = $ADForestInfo.Domains | Out-GridView -Title "Select AD Domain" -OutputMode Single
33+
34+
#Check for a valid DomainName
35+
if ($SelectedDomain -eq $null)
36+
{
37+
[System.Windows.MessageBox]::Show("AD Domain not selected","Error","OK","Error")
38+
exit
39+
}
40+
41+
#Find the right AD Domain Controller
42+
$dc = Get-ADDomainController -DomainName $SelectedDomain -Discover -NextClosestSite
43+
44+
#Get all groups from selected and select source and destination groups
45+
$ADGroupList = Get-ADGroup -filter * -Server $SelectedDomain | sort name | select Name
46+
$SourceGroup = $ADGroupList | Out-GridView -Title "Select the AD Group Name who's members needs to be copied" -OutputMode Single
47+
$DestinationGroup = $ADGroupList | Out-GridView -Title "Select the AD Group Name that needs to be populated" -OutputMode Single
48+
49+
#Basic checks for selecte groups
50+
if ($SourceGroup -eq $null)
51+
{
52+
[System.Windows.MessageBox]::Show("Source group not selected","Error","OK","Error")
53+
exit 1
54+
}
55+
56+
if ($DestinationGroup -eq $null)
57+
{
58+
[System.Windows.MessageBox]::Show("Destination group not selected","Error","OK","Error")
59+
exit 1
60+
}
61+
62+
if ($SourceGroup -eq $DestinationGroup)
63+
{
64+
[System.Windows.MessageBox]::Show("Source and Destination groups can not be the same","Error","OK","Error")
65+
exit 1
66+
}
67+
68+
#Fetch all members from selecte source group
69+
$member = Get-ADGroupMember -Identity $SourceGroup.Name -Server $dc.HostName[0]
70+
71+
#Try to populate the selected destination group with members
72+
Try
73+
{
74+
Add-ADGroupMember -Identity $DestinationGroup.name -Members $member -Server $dc.HostName[0]
75+
$message = "Members of AD Group " + $SourceGroup.name + " have been copied to AD Group " + $DestinationGroup.Name
76+
[System.Windows.MessageBox]::Show($message,"Finished","OK","Asterisk")
77+
}
78+
Catch
79+
{
80+
[System.Windows.MessageBox]::Show("AD Group membership copy failed","Error","OK","Error")
81+
}

Windows/Microsoft-ProfileCleaner.ps1

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
Param
2+
(
3+
[switch]$RunOnce = $False
4+
)
5+
<#
6+
.SYNOPSIS
7+
Clean up (partial) local profiles that are not in use anymore.
8+
.DESCRIPTION
9+
This script provides a way to delete local (copies) of user profiles that are not in use anymore. There is an option to exclude specified accounts. Special accounts like SYSTEM are always excluded
10+
.PARAMETER RunOnce
11+
By default, the script will loop continuously, use this parameter to run it only once
12+
.INPUTS
13+
None
14+
.OUTPUTS
15+
Logfile
16+
.NOTES
17+
Version: 1.0
18+
Author: Bart Jacobs - @Cloudsparkle
19+
Creation Date: 17/04/2020
20+
Purpose/Change: Remove obsolete local profiles
21+
22+
.EXAMPLE
23+
None
24+
#>
25+
26+
# Usernames to be excluded
27+
$Exclusions = "P-SVC-ACCOUNT1, P-SVC-ACCOUNT2"
28+
$Exclusions = $Exclusions.tolower()
29+
30+
# Set the output folder for the logfile
31+
$currentDir = Split-Path $MyInvocation.MyCommand.Path
32+
$outputdir = $currentDir
33+
34+
# Set the filename for the logfile
35+
$logfilename = "ProfilesDeleted.txt"
36+
37+
# Path and filename for logfile
38+
$logfile = Join-Path $outputdir $logfilename
39+
40+
# Script loop
41+
while ($true)
42+
{
43+
# Write-host "Starting scriptloop"
44+
Try {$profiles = Get-WmiObject -Class Win32_UserProfile}
45+
Catch
46+
{
47+
Write-Warning "Failed to retreive user profiles"
48+
Exit 1
49+
}
50+
51+
ForEach ($profile in $profiles)
52+
{
53+
# Retreiving profiledata
54+
$sid = New-Object System.Security.Principal.SecurityIdentifier($profile.SID)
55+
$account = $sid.Translate([System.Security.Principal.NTAccount])
56+
$accountDomain = $account.value.split("\")[0]
57+
$accountName = $account.value.split("\")[1]
58+
$profilePath = $profile.LocalPath
59+
$loaded = $profile.Loaded
60+
$special = $profile.Special
61+
$excluded = $false
62+
63+
# Convert the accountname to lower, to match the exclusions
64+
$accountname = $accountname.tolower()
65+
66+
if ($Exclusions.Contains($accountName))
67+
{
68+
$excluded = $true
69+
}
70+
71+
if (-Not $loaded -and -not $special -and -not $excluded)
72+
{
73+
Try
74+
{
75+
$profile.Delete()
76+
# Write-Host "Profile deleted successfully" -ForegroundColor Green
77+
$logEntry = ((Get-Date -uformat "%D %T") + " - Profile deleted successfully: " + $accountname)
78+
$logEntry | Out-File $logFile -Append
79+
}
80+
Catch
81+
{
82+
Write-Host "Error deleting profile" -ForegroundColor Red
83+
write-host $accountName -ForegroundColor Red
84+
$logEntry = ((Get-Date -uformat "%D %T") + " - ERROR Deleting profile: " + $accountname)
85+
$logEntry | Out-File $logFile -Append
86+
}
87+
}
88+
}
89+
90+
if ($RunOnce -eq $True)
91+
{
92+
write-host "Running Once, exiting now"
93+
Exit 0
94+
}
95+
96+
#Sleeping 30 seconds before the next run
97+
Write-Host "Sleeping..."
98+
start-sleep -s 30
99+
}

0 commit comments

Comments
 (0)