├── Classes ├── IADGroup.ps1 └── IADUser.ps1 ├── Functions ├── Add-IADOUUsersToGroups.ps1 ├── ConvertTo-IADDomain.ps1 ├── Delete-IADDisabledUsers.ps1 ├── Disable-IADComputer.ps1 ├── Disable-IADInactiveComputers.ps1 ├── Disable-IADInactiveUsers.ps1 ├── Disable-IADUser.ps1 ├── Empty-IADComputersContainer.ps1 ├── Get-IADGroupMember.ps1 ├── Get-IADUser.ps1 ├── Move-IADDisabledComputers.ps1 ├── Move-IADDisabledUsers.ps1 ├── Move-IADEnabledComputers.ps1 └── Move-IADEnabledUsers.ps1 ├── ImprovedActiveDirectory.psd1 ├── ImprovedActiveDirectory.psm1 ├── LICENSE ├── README.md ├── Tests ├── ConvertTo-IADDoman.tests.ps1 └── ImprovedActiveDirectory.Tests.ps1 └── en-US └── about_ImprovedActiveDirectory.help.txt /Classes/IADGroup.ps1: -------------------------------------------------------------------------------- 1 | using module ActiveDirectory 2 | using assembly Microsoft.ActiveDirectory.Management 3 | 4 | class ADGroupMember { 5 | [string]$distinguishedName 6 | [string]$name 7 | [string]$objectClass 8 | [string]$objectGUID 9 | [string]$SamAccountName 10 | [string]$SID 11 | 12 | ADGroupMember ($distinguishedName,$name,$objectClass,$objectGUID,$SamAccountName,$SID){ 13 | $this.distinguishedName = $distinguishedName 14 | $this.name = $name 15 | $this.objectClass = $objectClass 16 | $this.objectGUID = $objectGUID 17 | $this.SamAccountName = $SamAccountName 18 | $this.SID = $SID 19 | } 20 | 21 | [ADGroupMember]Object(){ 22 | return $this 23 | } 24 | } 25 | 26 | class IADGroup { 27 | [string]$Identity 28 | [object[]]$Properties 29 | [string]$Server = (Get-ADDomain).DNSroot 30 | 31 | IADGroup([Hashtable]$parameters) 32 | { 33 | $type = $this.GetType() 34 | $hashproperties = $type.GetProperties() 35 | 36 | foreach($property in $hashproperties) 37 | { 38 | if($parameters.ContainsKey($property.Name) -and $parameters[$property.Name] -ne $null) 39 | { 40 | $property.SetValue($this, $parameters[$property.Name]) 41 | } 42 | } 43 | } 44 | 45 | [object]GetGroup(){ 46 | 47 | $splat = $this.Hash() 48 | return Get-ADgroup @splat 49 | } 50 | 51 | [object]NestedMembers(){ 52 | $members = $this.DirectMembers($this.Identity,$this.Server) 53 | 54 | $memberships = foreach ($member in $members) { 55 | 56 | $Domain = ((($member.DistinguishedName -replace "(.*?)DC=(.*)",'$2') -replace "DC=","") -replace ",",".") 57 | 58 | switch ($member.objectClass) { 59 | 60 | 'group' { 61 | $property = Get-ADGroup -Identity $member.DistinguishedName -Server $Domain 62 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.sid) 63 | $this.NestedMembers($member.DistinguishedName,$Domain) 64 | } 65 | 66 | 'user' { 67 | try { 68 | $property = Get-ADUser -Identity $member.DistinguishedName -Server $Domain 69 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.sid) 70 | 71 | } catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] { 72 | 73 | $errors = Write-Warning -Message "$($member.DistinguishedName) not found" 74 | } 75 | } 76 | 77 | 'computer' { 78 | $property = Get-ADComputer -Identity $member.DistinguishedName -Server $Domain 79 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.sid) 80 | } 81 | 82 | 'foreignSecurityPrincipal' { 83 | $property = Get-ADObject -Identity $Member.DistinguishedName -Server $Domain -Properties objectsid | select distinguishedName,name,objectClass,objectGuid,samaccountname,objectSID 84 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.objectsid) 85 | } 86 | } 87 | } 88 | 89 | return $memberships 90 | return $errors 91 | } 92 | 93 | [object]NestedMembers([string]$Identity,[string]$Server){ 94 | $members = $this.DirectMembers($Identity,$Server) 95 | 96 | $memberships = foreach ($member in $members) { 97 | 98 | $Domain = ((($member.DistinguishedName -replace "(.*?)DC=(.*)",'$2') -replace "DC=","") -replace ",",".") 99 | 100 | switch ($member.objectClass) { 101 | 102 | 'group' { 103 | $property = Get-ADGroup -Identity $member.DistinguishedName -Server $Domain 104 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.sid) 105 | $this.NestedMembers($member.DistinguishedName,$Domain) 106 | } 107 | 108 | 'user' { 109 | try { 110 | $property = Get-ADUser -Identity $member.DistinguishedName -Server $Domain 111 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.sid) 112 | 113 | } catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] { 114 | 115 | $errors = Write-Warning -Message "$($member.DistinguishedName) not found" 116 | } 117 | } 118 | 119 | 'computer' { 120 | $property = Get-ADComputer -Identity $member.DistinguishedName -Server $Domain 121 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.sid) 122 | } 123 | 124 | 'foreignSecurityPrincipal' { 125 | $property = Get-ADObject -Identity $Member.DistinguishedName -Server $Domain -Properties objectsid | select distinguishedName,name,objectClass,objectGuid,samaccountname,objectSID 126 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.objectsid) 127 | } 128 | } 129 | } 130 | 131 | return $memberships 132 | return $errors 133 | } 134 | 135 | [object]DirectMembers(){ 136 | 137 | try { 138 | 139 | #$splat = $this.Hash() 140 | #if(!$splat.Properties.Contains('member')){$splat.Properties = $splat.Properties += 'member'} 141 | 142 | $memberships = Get-ADGroupMember -Identity $this.Identity -Server $this.Server 143 | } 144 | Catch [Microsoft.ActiveDirectory.Management.ADException] { 145 | 146 | $ADGroupMembers = (Get-ADGroup -Identity $this.Identity -Server $this.Server -Properties member).member 147 | 148 | $memberships = foreach($Member in $ADGroupMembers){ 149 | 150 | $ObjectDomain = ((($member -replace "(.*?)DC=(.*)",'$2') -replace "DC=","") -replace ",",".") 151 | $ADObject = Get-ADObject -Identity $Member -Server $ObjectDomain 152 | 153 | switch ($ADObject.ObjectClass) { 154 | 'group' { 155 | $property = Get-ADGroup -Identity $member -Server $ObjectDomain | select distinguishedName,name,objectClass,objectGuid,samaccountname,SID 156 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.sid) 157 | 158 | } 159 | 'user' { 160 | $property = Get-ADUser -Identity $Member -Server $ObjectDomain | select distinguishedName,name,objectClass,objectGuid,samaccountname,SID 161 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.sid) 162 | 163 | } 164 | 'foreignSecurityPrincipal' { 165 | $property = Get-ADObject -Identity $Member -Server $ObjectDomain -Properties objectSid | select distinguishedName,name,objectClass,objectGuid,samaccountname,objectSID 166 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.objectsid) 167 | } 168 | 'computer' { 169 | $property = Get-ADComputer -Identity $Member -Server $ObjectDomain | select distinguishedName,name,objectClass,objectGuid,samaccountname,objectSID 170 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.sid) 171 | } 172 | } 173 | } 174 | } 175 | if ($memberships){ 176 | return $memberships 177 | } else { 178 | return $null 179 | } 180 | 181 | } 182 | 183 | [object]DirectMembers([string]$Identity,[string]$Server){ 184 | try { 185 | 186 | 187 | $memberships = Get-ADGroupMember -Identity $Identity -Server $Server 188 | } 189 | Catch [Microsoft.ActiveDirectory.Management.ADException] { 190 | 191 | $ADGroupMembers = (Get-ADGroup -Identity $Identity -Server $Server -Properties member).member 192 | 193 | $memberships = foreach($Member in $ADGroupMembers){ 194 | 195 | $ObjectDomain = ((($member -replace "(.*?)DC=(.*)",'$2') -replace "DC=","") -replace ",",".") 196 | $ADObject = Get-ADObject -Identity $Member -Server $ObjectDomain 197 | 198 | switch ($ADObject.ObjectClass) { 199 | 'group' { 200 | $property = Get-ADGroup -Identity $member -Server $ObjectDomain | select distinguishedName,name,objectClass,objectGuid,samaccountname,SID 201 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.sid) 202 | 203 | } 204 | 'user' { 205 | $property = Get-ADUser -Identity $Member -Server $ObjectDomain | select distinguishedName,name,objectClass,objectGuid,samaccountname,SID 206 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.sid) 207 | 208 | } 209 | 'foreignSecurityPrincipal' { 210 | $property = Get-ADObject -Identity $Member -Server $ObjectDomain -Properties objectSid | select distinguishedName,name,objectClass,objectGuid,samaccountname,objectSID 211 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.objectsid) 212 | } 213 | 'computer' { 214 | $property = Get-ADComputer -Identity $Member -Server $ObjectDomain | select distinguishedName,name,objectClass,objectGuid,samaccountname,objectSID 215 | [ADGroupMember]::New($property.distinguishedName,$property.name,$property.objectclass,$property.objectguid,$property.samaccountname,$property.sid) 216 | } 217 | } 218 | } 219 | } 220 | 221 | if ($memberships){ 222 | return $memberships 223 | } else { 224 | return $null 225 | } 226 | } 227 | 228 | [hashtable]Hash(){ 229 | $type = $this.GetType() 230 | $hashproperties = $type.GetProperties() 231 | 232 | $splat = @{} 233 | foreach($property in $hashproperties) 234 | { 235 | if ($this.($property.Name) -ne $null){ 236 | $splat.Add($($property.Name),$($this.($property.Name))) 237 | } 238 | } 239 | 240 | return $splat 241 | } 242 | 243 | } 244 | -------------------------------------------------------------------------------- /Classes/IADUser.ps1: -------------------------------------------------------------------------------- 1 | Class IADUser { 2 | 3 | } -------------------------------------------------------------------------------- /Functions/Add-IADOUUsersToGroups.ps1: -------------------------------------------------------------------------------- 1 | Function Add-IADOUUsersToGroups{ 2 | <# 3 | .SYNOPSIS 4 | Adds user accounts found inside an Active Directory OU to specified groups. 5 | .DESCRIPTION 6 | Add-IADOUUsersToGroups queries the specified OU, gathers all enabled user accounts, and adds them to the specified groups. Suggested application of this function is to use it inside a daily automated task to ensure a more organized Active Directory. 7 | .PARAMETER Server 8 | Specifies the Active Directory Domain Services instance to connect to. 9 | .PARAMETER Credential 10 | Specifies the credentials used to modify the objects. Functions the same way as Active Directory cmdlets (PSCredential). 11 | .PARAMETER TargetOU 12 | Specifies the target organizational unit containing the users you want to add. This parameter accepts the distinguishedname of the OU as a string. 13 | .PARAMETER Groups 14 | Specifies the group or groups to add the users to. This parameter accepts a string array of samaccountnames. 15 | .PARAMETER ExclusionList 16 | Specify which accounts if any need to be excluded from the move. The parameter accepts a string array of samaccountnames. 17 | .PARAMETER WhatIf 18 | Supports the SwitchParameter WhatIf. If specified the function will return what would happen if it was ran, taking no action. Use this to see what accounts are targeted without actually moving them. 19 | .PARAMETER Confirm 20 | Supports the SwitchParameter Confirm. If specified the function will ask for confirmation before modifying each account. If you do not specify -Confirm it will move the objects without asking. 21 | .EXAMPLE 22 | Add-IADOUUsersToGroups -Server fabrikom.com -Credential (get-credential) -TargetOU "OU=UserAccounts,DC=fabrikom,DC=com" -Groups Group1,Group2 -ExclusionList test1,test2,test3 -Confirm 23 | 24 | Queries the fabrikom.com domain after prompting for credentials to use. Will ask for confirmation before adding users to Group1 and Group2, and excludes user accounts test1, test2, and test3. 25 | .EXAMPLE 26 | Add-IADOUUsersToGroups -Credential $Creds -DisabledOU -Server fabrikom.com -TargetOU "OU=UserAccounts,DC=fabrikom,DC=com" -Groups Group -WhatIf 27 | 28 | Queries the fabrikom.com domain using credentials stored inside the $Creds PSCredential object and returns what will happen, but does not take action (-WhatIf). 29 | .EXAMPLE 30 | $A = Add-IADOUUsersToGroups -Server fabrikom.com -Credential (get-credential) -TargetOU "OU=UserAccounts,DC=fabrikom,DC=com" -Groups Group1,Group2 -ExclusionList test1,test2,test3 31 | $A | where Status -like "Failure" 32 | 33 | Displays errors encountered if you receive a failure when adding users to groups. 34 | #> 35 | [CmdletBinding()] 36 | param([Parameter(Mandatory=$true)] 37 | [string]$Server, 38 | [Parameter(Mandatory=$true)] 39 | [System.Management.Automation.PSCredential]$Credential, 40 | [Parameter(Mandatory=$true)] 41 | [string]$TargetOU, 42 | [Parameter(Mandatory=$true)] 43 | [string[]]$Groups, 44 | [string[]]$ExclusionList, 45 | [switch]$Confirm, 46 | [switch]$WhatIf) 47 | 48 | $ReturnList = @() 49 | 50 | #Verify OU 51 | if((Get-ADOrganizationalUnit -Server $Server -filter{distinguishedname -like $TargetOU}) -eq $null){throw "$TargetOU not found in $Server domain"} 52 | 53 | 54 | #Build the string for the filter exclusion list 55 | if($ExclusionList){ 56 | foreach($Account in $ExclusionList){ 57 | if(!$FilterExclusionList){$FilterExclusionList += "enabled -eq `$true -and samaccountname -notlike `"$Account`""} 58 | else{$FilterExclusionList += " -and samaccountname -notlike `"$Account`""} 59 | } 60 | } 61 | 62 | else{$FilterExclusionList = "enabled -eq `$true"} 63 | 64 | 65 | #Gather the user objects inside the $TargetOU and exclude $FilterExclusionList 66 | $OUUsers = Get-ADUser -Server $Server -Filter $FilterExclusionList -SearchBase $TargetOU 67 | 68 | 69 | #Add each user account to the $Groups 70 | if($OUUsers){ 71 | foreach($User in $OUUsers){ 72 | foreach($Group in $Groups){ 73 | 74 | Try{ 75 | Add-ADGroupMember -Server $Server -Identity $Group -Members $User -Credential $Credential -Confirm:$Confirm -Whatif:$WhatIf -Verbose 76 | $A = [pscustomobject]@{"User"=$User.samaccountname; 77 | "Group"=$Group; 78 | "Status"="Successful"} 79 | } 80 | 81 | Catch{ 82 | $A = [pscustomobject]@{"User"=$User.samaccountname; 83 | "Group"=$Group; 84 | "Status"="Failure"; 85 | "Error"=$Error[0]} 86 | } 87 | 88 | $ReturnList += $A 89 | } 90 | } 91 | } 92 | 93 | else{$ReturnList = "No users found inside $TargetOU"} 94 | 95 | Return $ReturnList 96 | 97 | } -------------------------------------------------------------------------------- /Functions/ConvertTo-IADDomain.ps1: -------------------------------------------------------------------------------- 1 | function ConvertTo-IADDomain 2 | { 3 | [CmdletBinding()] 4 | Param 5 | ( 6 | [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,Position=0)] 7 | [string[]]$distinguishedname 8 | ) 9 | 10 | Begin 11 | { 12 | 13 | } 14 | Process { 15 | 16 | foreach ($DN in $distinguishedname) { 17 | if ($DN -match 'CN=[^"/\\\[\]:;|=,+\*\?<>*]{1,64},(CN=[^"/\\\[\]:;|=,+\*\?<>*]{1,64})?,(DC=[^"/\\:*?<>|]{1,15})?,DC=[^"/\\:*?<>|]{1,15}') { 18 | ((($DN -replace "(.*?)DC=(.*)",'$2') -replace "DC=","") -replace ",",".") 19 | } else { 20 | Write-Error -message "$DN is not a valid distinguishedname" 21 | } 22 | } 23 | } 24 | End 25 | { 26 | 27 | } 28 | } -------------------------------------------------------------------------------- /Functions/Delete-IADDisabledUsers.ps1: -------------------------------------------------------------------------------- 1 | Function Delete-IADDisabledUsers{ 2 | <# 3 | .SYNOPSIS 4 | Disables all inactive computer accounts found inside a domain to the specified OU for disabled computers. 5 | .DESCRIPTION 6 | Disable-IADInactiveComputers queries the specified domain, gathers all inactive computer accounts, and moves them to the Active Directory path provided by operator. Inactivity is determined using the lastlogontimestamp of the computer. Default behavior of the command will target Workstation Operating Systems only (Windows 7, 8, 10, and XP). Suggested application of this function is to use it inside a daily automated task to ensure a more organized Active Directory. 7 | .PARAMETER Server 8 | Specifies the Active Directory Domain Services instance to connect to. 9 | .PARAMETER Credential 10 | Specifies the credentials used to move the objects. Functions the same way as Active Directory cmdlets (PSCredential). 11 | .PARAMETER DisabledOU 12 | Specifies the target organizational unit to move the objects to. This parameter accepts the distinguishedname of the OU as a string. 13 | .PARAMETER DaysInactive 14 | Specifies the amount of days of inactivity to target. Accepts an integer for input and checks against the lastlogontimestamp of the computer account. 15 | .PARAMETER ExclusionList 16 | Specifies what machine names to exclude from the command. Input the name property of a computer account and it will leave it out of the query. Accepts string array input. 17 | .PARAMETER IncludeServers 18 | Supports the SwitchParameter IncludeServers, which tells the command to also query and disable inactive Windows Server machines. 19 | .PARAMETER IncludeAll 20 | Supports the SwitchParameter IncludeAll, which tells the command to query for ALL computer accounts that are inactive. This may include Mac OSX, Linux, Storage devices, etc. Be careful using this as some machine types joined may not have functionality to update their lastlogontimestmap but require domain membership. 21 | .PARAMETER WhatIf 22 | Supports the SwitchParameter WhatIf. If specified the function will return what would happen if it was ran, taking no action. Use this to see what accounts are targeted without actually moving them. 23 | .PARAMETER Confirm 24 | Supports the SwitchParameter Confirm. If specified the function will ask for confirmation before moving each account. If you do not specify -Confirm it will move the objects without asking. 25 | .EXAMPLE 26 | Disable-IADInactiveComputers -Server fabrikom.com -Credential (Get-Credential) -DisabledOU "OU=Disabled,DC=fabrikom,DC=com" -DaysInactive 90 -WhatIf -IncludeServers 27 | 28 | Queries the fabrikom.com domain after prompting for credentials to use. Includes both desktop and server computer objects that have not logged on for 90 days. Returns what will happen, but does not take action (-WhatIf). 29 | .EXAMPLE 30 | Disable-IADInactiveComputers -Server fabrikom.com -Credential $Creds -DisabledOU "OU=Disabled,DC=fabrikom,DC=com" -DaysInactive 180 31 | 32 | Queries the currently joined domain using credentials stored inside the $Creds PSCredential object. Queries and disables all desktop computers that have not logged on for 180 days. 33 | #> 34 | [CmdletBinding()] 35 | param([string]$Server, 36 | [System.Management.Automation.PSCredential]$Credential, 37 | [Parameter(Mandatory=$true)] 38 | [string]$DisabledOU, 39 | [Parameter(Mandatory=$true)] 40 | [int]$DaysDisabled, 41 | [string[]]$ExclusionList, 42 | [switch]$NoRecycleBin, 43 | [switch]$Confirm, 44 | [switch]$WhatIf) 45 | 46 | $ReturnList = @() 47 | $FilterExclusionList = "" 48 | 49 | #Build the $FilterString from the $ExclusionList 50 | $FirstPass = "1" 51 | foreach($Account in $ExclusionList){ 52 | if($FirstPass -like "1"){$FilterExclusionList += "samaccountname -notlike `"$Account`""} 53 | else{$FilterExclusionList += " -and samaccountname -notlike `"$Account`""} 54 | $FirstPass = "0" 55 | } 56 | $FilterString = "$FilterExclusionList" 57 | 58 | #Write message if AD Recycle Bin not enabled and switchparameter -NoRecycleBin not specified 59 | if( (!(Get-ADOptionalFeature -filter{name -like "Recycle Bin Feature"}).EnabledScopes) -and !($NoRecycleBin)){ 60 | Write-Host "!!WARNING!! AD Recycle Bin is not enabled! Proceed with caution! Use -NoRecycleBin to ignore next time." -ForegroundColor Red -BackgroundColor Black 61 | sleep 10 62 | Write-Host "Resuming command..." -ForegroundColor Red -BackgroundColor Black 63 | } 64 | 65 | #Gather the disabled accounts 66 | $DisabledUsers = Get-ADUser -SearchBase $DisabledOU -Server $Server -Filter $FilterString -Properties description | Where-Object {$_.enabled -eq $false} 67 | 68 | 69 | #Disable, set, and move each computer account to the specified $DisabledOU 70 | if($InactiveComputers){ 71 | foreach($Computer in $InactiveComputers){ 72 | 73 | Try{ 74 | $Description = $($Computer.description) + " / " + "Disabled on $CurrentDate due to $Daysinactive days inactive" 75 | Disable-ADAccount -Identity $Computer -Server $Server -Credential $Credential -Confirm:$Confirm -Whatif:$WhatIf -Verbose 76 | Set-ADObject -Identity $Computer -Server $Server -Credential $Credential -Description $Description -Confirm:$Confirm -Whatif:$WhatIf -Verbose 77 | Move-ADObject -Identity $Computer -Server $Server -Credential $Credential -TargetPath $DisabledOU -Confirm:$Confirm -Whatif:$WhatIf -Verbose 78 | 79 | $A = [pscustomobject]@{"Computer"=$Computer.dnshostname; 80 | "Status"="Successful"; 81 | "LastLogin"=$([datetime]::FromFileTime($Computer.Lastlogontimestamp)); 82 | "OS"=$Computer.operatingsystem} 83 | } 84 | 85 | Catch{ 86 | $A = [pscustomobject]@{"Computer"=$Computer.dnshostname; 87 | "Status"="Failure"; 88 | "Error"=$Error[0]; 89 | "LastLogin"=$([datetime]::FromFileTime($Computer.Lastlogontimestamp)); 90 | "OS"=$Computer.operatingsystem} 91 | } 92 | 93 | $ReturnList += $A 94 | 95 | } 96 | } 97 | 98 | else{$ReturnList = "No inactive computers found"} 99 | 100 | return $ReturnList 101 | } 102 | 103 | # [0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9] -------------------------------------------------------------------------------- /Functions/Disable-IADComputer.ps1: -------------------------------------------------------------------------------- 1 | function Disable-IADComputer { 2 | <# 3 | .SYNOPSIS 4 | Disables Computers and moves them to the specified OU. 5 | .DESCRIPTION 6 | Take string or object input for computers then disables each one and moves to the specified ou 7 | then outputs errors to a log file. 8 | .PARAMETER Identity 9 | Name of computer or computers 10 | .PARAMETER DisabledOU 11 | Specifies the Distinguished Name of the OU the device will be moved to. 12 | .PARAMETER Domain 13 | Specifies the domain in which to query for the computer given to the ComputerName parameter. If left blank it will query the domain of the currently logged on user. 14 | .PARAMETER Description 15 | By default this will append to the existing description of the computer object and append any text given to this parameter. 16 | .PARAMETER PSCredential 17 | Allows the use of alternate credentials in for form doman\user. 18 | .EXAMPLE 19 | Disable-ADComputer -Identity computer1 -DisabledOU 'OU=Computers,OU=Disabled Accounts,DC=domain,DC=com' -Description "CR00001' -Domain domain.forest.com -Verbose -whatif 20 | .EXAMPLE 21 | Disable-ADComputer -Identity computer1 -PSCredential domain\user -Description "CR00002" -verbose 22 | #> 23 | [CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact='Medium')] 24 | param( 25 | [Parameter(Mandatory=$true,ValueFromPipeline=$true,Position=0)] 26 | [string[]]$Identity, 27 | [string]$DisabledOU, 28 | [string]$Domain = (Get-ADDomain).DNSroot, 29 | [string]$Description = $null, 30 | [string]$ErrorLog = "$env:SystemDrive\retry.txt", 31 | $PSCredential 32 | ) 33 | BEGIN { 34 | 35 | Write-Verbose -Message "Starting Disable-ADComputer" 36 | if ($PSCredential){ 37 | $SecurePassword = Read-Host -Prompt "Enter Password" -AsSecureString 38 | $PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $PSCredential,$SecurePassword 39 | } 40 | } 41 | 42 | PROCESS { 43 | 44 | foreach($ID in $Identity){ 45 | 46 | 47 | Try { 48 | 49 | $GetParms = @{ 50 | 'Identity' = $ID 51 | 'Server' = $Domain 52 | } 53 | 54 | if ($Description) {$GetParms.Add('Properties','Description')} 55 | if ($PSCredential) {$GetParms.Add('Credential',$PSCredential)} 56 | 57 | $ComputerInfo = Get-ADComputer @GetParms 58 | $Description = $($ComputerInfo.Description) + " "+ $Description 59 | 60 | $SetParms = @{ 61 | 'Identity' = $ID 62 | 'Server' = $Domain 63 | 'Enabled' = $false 64 | } 65 | 66 | if ($Description -ne ' ') {$SetParms.Add('Description',$Description)} 67 | if ($PSCredential) {$SetParms.Add('Credential',$PSCredential)} 68 | 69 | Write-Verbose -Message "Disabling $ID" 70 | 71 | Set-ADComputer @SetParms 72 | 73 | if ($DisabledOU){ 74 | 75 | $MoveParms = @{ 76 | 'Identity' = $($ComputerInfo.DistinguishedName) 77 | 'TargetPath' = $DisabledOU 78 | 'Server' = $Domain 79 | } 80 | if ($PSCredential) {$MoveParms.Add('Credential',$PSCredential)} 81 | 82 | Write-Verbose -Message "Moving $ID to $DisabledOU" 83 | 84 | Move-ADObject @MoveParms 85 | } 86 | 87 | } 88 | Catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException]{ 89 | Write-Warning -Message "$Identity was not found" 90 | Write-Output -InputObject $Identity | Out-File $ErrorLog 91 | } 92 | Catch { 93 | Write-Warning -Message $_.Exception.Message 94 | } 95 | } 96 | } 97 | END { 98 | Write-Verbose -Message "Finished" 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Functions/Disable-IADInactiveComputers.ps1: -------------------------------------------------------------------------------- 1 | Function Disable-IADInactiveComputers{ 2 | <# 3 | .SYNOPSIS 4 | Disables all inactive computer accounts found inside a domain to the specified OU for disabled computers. 5 | .DESCRIPTION 6 | Disable-IADInactiveComputers queries the specified domain, gathers all inactive computer accounts, and moves them to the Active Directory path provided by operator. Inactivity is determined using the lastlogontimestamp of the computer. Default behavior of the command will target Workstation Operating Systems only (Windows 7, 8, 10, and XP). Suggested application of this function is to use it inside a daily automated task to ensure a more organized Active Directory. 7 | .PARAMETER Server 8 | Specifies the Active Directory Domain Services instance to connect to. 9 | .PARAMETER Credential 10 | Specifies the credentials used to move the objects. Functions the same way as Active Directory cmdlets (PSCredential). 11 | .PARAMETER DisabledOU 12 | Specifies the target organizational unit to move the objects to. This parameter accepts the distinguishedname of the OU as a string. 13 | .PARAMETER DaysInactive 14 | Specifies the amount of days of inactivity to target. Accepts an integer for input and checks against the lastlogontimestamp of the computer account. 15 | .PARAMETER ExclusionList 16 | Specifies what machine names to exclude from the command. Input the name property of a computer account and it will leave it out of the query. Accepts string array input. 17 | .PARAMETER IncludeServers 18 | Supports the SwitchParameter IncludeServers, which tells the command to also query and disable inactive Windows Server machines. 19 | .PARAMETER IncludeAll 20 | Supports the SwitchParameter IncludeAll, which tells the command to query for ALL computer accounts that are inactive. This may include Mac OSX, Linux, Storage devices, etc. Be careful using this as some machine types joined may not have functionality to update their lastlogontimestmap but require domain membership. 21 | .PARAMETER WhatIf 22 | Supports the SwitchParameter WhatIf. If specified the function will return what would happen if it was ran, taking no action. Use this to see what accounts are targeted without actually moving them. 23 | .PARAMETER Confirm 24 | Supports the SwitchParameter Confirm. If specified the function will ask for confirmation before moving each account. If you do not specify -Confirm it will move the objects without asking. 25 | .EXAMPLE 26 | Disable-IADInactiveComputers -Server fabrikom.com -Credential (Get-Credential) -DisabledOU "OU=Disabled,DC=fabrikom,DC=com" -DaysInactive 90 -WhatIf -IncludeServers 27 | 28 | Queries the fabrikom.com domain after prompting for credentials to use. Includes both desktop and server computer objects that have not logged on for 90 days. Returns what will happen, but does not take action (-WhatIf). 29 | .EXAMPLE 30 | Disable-IADInactiveComputers -Server fabrikom.com -Credential $Creds -DisabledOU "OU=Disabled,DC=fabrikom,DC=com" -DaysInactive 180 31 | 32 | Queries the currently joined domain using credentials stored inside the $Creds PSCredential object. Queries and disables all desktop computers that have not logged on for 180 days. 33 | #> 34 | [CmdletBinding()] 35 | param([string]$Server, 36 | [System.Management.Automation.PSCredential]$Credential, 37 | [Parameter(Mandatory=$true)] 38 | [string]$DisabledOU, 39 | [Parameter(Mandatory=$true)] 40 | [int]$DaysInactive, 41 | [string[]]$ExclusionList, 42 | [switch]$IncludeServers, 43 | [switch]$IncludeAll, 44 | [switch]$Confirm, 45 | [switch]$WhatIf) 46 | 47 | $ReturnList = @() 48 | $FilterExclusionList = "" 49 | 50 | #Grab current date for description and set the $DaysInactive as [datetime] data type for use with lastlogontimestamp 51 | $CurrentDate = Get-Date -UFormat %D 52 | $InactiveDate = ((Get-Date).AddDays(-$DaysInactive)) 53 | 54 | 55 | #Build the $FilterString from the $ExclusionList 56 | $FirstPass = "1" 57 | foreach($Account in $ExclusionList){ 58 | if($FirstPass -like "1"){$FilterExclusionList += "name -notlike `"$Account`""} 59 | else{$FilterExclusionList += " -and name -notlike `"$Account`""} 60 | $FirstPass = "0" 61 | } 62 | $FilterString = "$FilterExclusionList" 63 | 64 | #Gather the inactive computer accounts 65 | if($IncludeServers -and $IncludeAll){throw "You may only specify one option: -IncludeServers, -IncludeAll, or neither for default behavior"} 66 | 67 | if($IncludeAll){ 68 | if($FilterString){$InactiveComputers = Get-ADComputer -Server $Server -Filter $FilterString -Properties lastlogontimestamp,description,operatingsystem ` 69 | | Where-Object {$_.lastlogontimestamp -lt $($InactiveDate.ToFileTime()) -and $_.enabled -eq $true}} 70 | 71 | else{$InactiveComputers = Get-ADComputer -Server $Server -Filter{lastlogontimestamp -lt $InactiveDate -and enabled -eq $true} -Properties lastlogontimestamp,description,operatingsystem} 72 | } 73 | 74 | if($IncludeServers){ 75 | if($FilterString){$InactiveComputers = Get-ADComputer -Server $Server -Filter $FilterString -Properties lastlogontimestamp,description,operatingsystem ` 76 | | Where-Object {$_.lastlogontimestamp -lt $($InactiveDate.ToFileTime())} -and $_.operatingsystem -like "Windows Server*" -and $_.enabled -eq $true} 77 | 78 | else{$InactiveComputers = Get-ADComputer -Server $Server -Filter{lastlogontimestamp -lt $InactiveDate -and operatingsystem -like "Windows Server*" -and enabled -eq $true} ` 79 | -Properties lastlogontimestamp,description,operatingsystem} 80 | } 81 | 82 | else{ 83 | if($FilterString){ 84 | $InactiveComputers = Get-ADComputer -Server $Server -Filter $FilterString -Properties lastlogontimestamp,description,operatingsystem ` 85 | | Where-Object {$_.lastlogontimestamp -lt $($InactiveDate.ToFileTime()) -and $_.enabled -eq $true -and ($_.operatingsystem -like "Windows 7*" ` 86 | -or $_.operatingsystem -like "Windows 8*" -or $_.operatingsystem -like "Windows XP*" -or $_.operatingsystem -like "Windows 10*")} 87 | } 88 | 89 | else{ 90 | $InactiveComputers = Get-ADComputer -Server $Server -Filter{lastlogontimestamp -lt $InactiveDate} -Properties lastlogontimestamp,description,operatingsystem ` 91 | | Where-Object {$_.enabled -eq $true -and ($_.operatingsystem -like "Windows 7*" -or $_.operatingsystem -like "Windows 8*" ` 92 | -or $_.operatingsystem -like "Windows XP*" -or $_.operatingsystem -like "Windows 10*")} 93 | } 94 | } 95 | 96 | #Disable, set, and move each computer account to the specified $DisabledOU 97 | if($InactiveComputers){ 98 | foreach($Computer in $InactiveComputers){ 99 | 100 | Try{ 101 | $Description = $($Computer.description) + " / " + "Disabled on $CurrentDate due to $Daysinactive days inactive" 102 | Disable-ADAccount -Identity $Computer -Server $Server -Credential $Credential -Confirm:$Confirm -Whatif:$WhatIf -Verbose 103 | Set-ADObject -Identity $Computer -Server $Server -Credential $Credential -Description $Description -Confirm:$Confirm -Whatif:$WhatIf -Verbose 104 | Move-ADObject -Identity $Computer -Server $Server -Credential $Credential -TargetPath $DisabledOU -Confirm:$Confirm -Whatif:$WhatIf -Verbose 105 | 106 | $A = [pscustomobject]@{"Computer"=$Computer.dnshostname; 107 | "Status"="Successful"; 108 | "LastLogin"=$([datetime]::FromFileTime($Computer.Lastlogontimestamp)); 109 | "OS"=$Computer.operatingsystem} 110 | } 111 | 112 | Catch{ 113 | $A = [pscustomobject]@{"Computer"=$Computer.dnshostname; 114 | "Status"="Failure"; 115 | "Error"=$Error[0]; 116 | "LastLogin"=$([datetime]::FromFileTime($Computer.Lastlogontimestamp)); 117 | "OS"=$Computer.operatingsystem} 118 | } 119 | 120 | $ReturnList += $A 121 | 122 | } 123 | } 124 | 125 | else{$ReturnList = "No inactive computers found"} 126 | 127 | return $ReturnList 128 | } 129 | 130 | -------------------------------------------------------------------------------- /Functions/Disable-IADInactiveUsers.ps1: -------------------------------------------------------------------------------- 1 | Function Disable-IADInactiveUsers{ 2 | <# 3 | .SYNOPSIS 4 | Disables all inactive user accounts found inside a domain to the specified OU for disabled users. 5 | .DESCRIPTION 6 | Disable-IADInactiveUsers queries the specified domain, gathers all inactive user accounts, and moves them to the Active Directory path provided by operator. Inactivity is determined using the lastlogontimestamp of the user. By default accounts that have never logged in are excluded, you can use the -IncludeNeverLoggedIn to put in scope. PLEASE NOTE, it is suggesed you first run the cmdlet with -WhatIf so you are aware of any unwanted accounts targeted like service or system accounts. Add any exceptions to the exclusion list and run again using -WhatIf to test they are truly excluded. Suggested application of this function is to use it inside a daily automated task to ensure a more organized Active Directory. 7 | .PARAMETER Server 8 | Specifies the Active Directory Domain Services instance to connect to. 9 | .PARAMETER Credential 10 | Specifies the credentials used to move the objects. Functions the same way as Active Directory cmdlets (PSCredential). 11 | .PARAMETER DisabledOU 12 | Specifies the target organizational unit to move the objects to. This parameter accepts the distinguishedname of the OU as a string. 13 | .PARAMETER DaysInactive 14 | Specifies the amount of days of inactivity to target. Accepts an integer for input and checks against the lastlogontimestamp of the user account. 15 | .PARAMETER ExclusionList 16 | Specifies what usernames to exclude from the command. Input the samaccountname property of a user account and it will leave it out of the query. Accepts string array input for multiple usernames. 17 | .PARAMETER IncludeNeverLoggedIn 18 | Supports the SwitchParameter IncludeNeverLoggedIn. If specified the function the will disable and move any user accounts that have never logged in (i.e. lastlogontimestamp is "12/31/1600 6:00:00 PM") but are enabled. Not recommended for most environments as this will disable any new accounts created ahead of time for employees that haven't started yet. 19 | .PARAMETER WhatIf 20 | Supports the SwitchParameter WhatIf. If specified the function will return what would happen if it was ran, taking no action. Use this to see what accounts are targeted without actually moving them. 21 | .PARAMETER Confirm 22 | Supports the SwitchParameter Confirm. If specified the function will ask for confirmation before moving each account. If you do not specify -Confirm it will move the objects without asking. 23 | .EXAMPLE 24 | Disable-IADInactiveUsers -Server fabrikom.com -Credential (Get-Credential) -DisabledOU "OU=Disabled,DC=fabrikom,DC=com" -DaysInactive 90 -WhatIf 25 | 26 | Queries the fabrikom.com domain after prompting for credentials for user accounts that have not logged on for more than 90 days but logged in at least once in the past. Returns what will happen, but does not take action (-WhatIf). 27 | .EXAMPLE 28 | Disable-IADInactiveUsers -Server fabrikom.com -Credential $Creds -DisabledOU "OU=Disabled,DC=fabrikom,DC=com" -DaysInactive 180 -IncludeNeverLoggedIn 29 | 30 | Queries the currently joined domain using credentials stored inside the $Creds PSCredential object. Queries and disables all user accounts that have not logged on for more than 180 days. 31 | #> 32 | [CmdletBinding()] 33 | param([string]$Server, 34 | [System.Management.Automation.PSCredential]$Credential, 35 | [Parameter(Mandatory=$true)] 36 | [string]$DisabledOU, 37 | [Parameter(Mandatory=$true)] 38 | [int]$DaysInactive, 39 | [string[]]$ExclusionList, 40 | [switch]$IncludeNeverLoggedIn, 41 | [switch]$Confirm, 42 | [switch]$WhatIf) 43 | 44 | $ReturnList = @() 45 | $FilterExclusionList = "" 46 | 47 | #Grab current date for description and set the $DaysInactive as [datetime] data type for use with lastlogontimestamp 48 | $CurrentDate = Get-Date -UFormat %D 49 | $InactiveDate = ((Get-Date).AddDays(-$DaysInactive)) 50 | 51 | #Build the string for the filter exclusion list 52 | foreach($Account in $ExclusionList){$FilterExclusionList += "-and samaccountname -notlike `"$Account`""} 53 | $FilterString = "enabled -eq `$true -and samaccountname -notlike `"krbtgt`" -and samaccountname -notlike `"Guest`" -and samaccountname -notlike `"DefaultAccount`" $FilterExclusionList" 54 | 55 | #Gather the user objects that are disabled and not inside the $DisabledOU or $ExclusionList 56 | #Include Users that have never logged in 57 | if($IncludeNeverLoggedIn){ 58 | $DisabledUsers = Get-ADUser -Server $Server -Filter $FilterString -Properties lastlogontimestamp,description | Where-Object {$_.lastlogontimestamp -lt $($InactiveDate.ToFileTime())} 59 | } 60 | 61 | #Exclude users that have never logged in 62 | else{ 63 | $NeverLoggedIn = (([DateTime]"12/31/1600 6:00:00 PM").ToFileTime()) 64 | $DisabledUsers = Get-ADUser -Server $Server -Filter $FilterString -Properties lastlogontimestamp,description | Where-Object {$_.lastlogontimestamp -lt $($InactiveDate.ToFileTime()) -and $_.lastlogontimestamp -gt $NeverLoggedIn} 65 | } 66 | 67 | 68 | #Disable, set, and move each user account 69 | if($DisabledUsers){ 70 | foreach($User in $DisabledUsers){ 71 | 72 | Try{ 73 | $Description = $($User.description) + " / " + "Disabled on $CurrentDate due to $Daysinactive days inactive" 74 | Disable-ADAccount -Server $Server -Identity $User -Credential $Credential -Confirm:$Confirm -WhatIf:$WhatIf -Verbose 75 | Set-ADObject -Server $Server -Identity $User -Credential $Credential -Description $Description -Confirm:$Confirm -WhatIf:$WhatIf -Verbose 76 | Move-ADObject -Server $Server -Identity $User -TargetPath $DisabledOU -Credential $Credential -Confirm:$Confirm -Whatif:$WhatIf -Verbose 77 | $A = [pscustomobject]@{"User"=$User.samaccountname; 78 | "LastLogin"=$([datetime]::FromFileTime($User.Lastlogontimestamp)); 79 | "Status"="Successful"} 80 | } 81 | 82 | Catch{ 83 | $A = [pscustomobject]@{"User"=$User.samaccountname; 84 | "Status"="Failure"; 85 | "LastLogin"=$([datetime]::FromFileTime($User.Lastlogontimestamp)); 86 | "Error"=$Error[0]} 87 | } 88 | 89 | $ReturnList += $A 90 | } 91 | } 92 | 93 | else{$ReturnList = "No users found"} 94 | 95 | Return ($ReturnList | sort lastlogin) 96 | 97 | } 98 | 99 | -------------------------------------------------------------------------------- /Functions/Disable-IADUser.ps1: -------------------------------------------------------------------------------- 1 | function Disable-IADUser { 2 | <# 3 | .SYNOPSIS 4 | Disables Users and moves them to the specified OU. 5 | .DESCRIPTION 6 | Take string or object input for Users then disables each one and moves to the specified ou 7 | then outputs errors to a log file. 8 | .PARAMETER Identity 9 | Name of user or Users 10 | .PARAMETER DisabledOU 11 | Specifies the Distinguished Name of the OU the device will be moved to. 12 | .PARAMETER Domain 13 | Specifies the domain in which to query for the user given to the Identity parameter. If left blank it will query the domain of the currently logged on user. 14 | .PARAMETER Description 15 | By default this will append to the existing description of the user object and append any text given to this parameter. 16 | .PARAMETER PSCredential 17 | Allows the use of alternate credentials in for form doman\user. 18 | .EXAMPLE 19 | Disable-ADUser -Identity user1 -DisabledOU 'OU=Users,OU=Disabled Accounts,DC=domain,DC=com' -Description "CR00001' -Domain domain.forest.com -Verbose 20 | .EXAMPLE 21 | Disable-ADUser -Identity user1 -PSCredential domain\user -Description "CR00002" -verbose 22 | #> 23 | [CmdletBinding()] 24 | param( 25 | [Parameter(Mandatory=$true,ValueFromPipeline=$true,Position=0)] 26 | [string[]]$Identity, 27 | [string]$DisabledOU, 28 | [string]$Domain = (Get-ADDomain).DNSroot, 29 | [string]$Description = $null, 30 | [string]$ErrorLog = "$env:SystemDrive\retry.txt", 31 | $PSCredential 32 | ) 33 | BEGIN { 34 | 35 | Write-Verbose -Message "Starting Disable-ADUser" 36 | if ($PSCredential){ 37 | $SecurePassword = Read-Host -Prompt "Enter Password" -AsSecureString 38 | $PSCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $PSCredential,$SecurePassword 39 | } 40 | } 41 | 42 | PROCESS { 43 | 44 | foreach($ID in $Identity){ 45 | 46 | 47 | Try { 48 | 49 | $GetParms = @{ 50 | 'Identity' = $ID 51 | 'Server' = $Domain 52 | } 53 | 54 | if ($Description) {$GetParms.Add('Properties','Description')} 55 | if ($PSCredential) {$GetParms.Add('Credential',$PSCredential)} 56 | 57 | $UserInfo = Get-ADUser @GetParms 58 | $Description = $($UserInfo.Description) + " "+ $Description 59 | 60 | $SetParms = @{ 61 | 'Identity' = $ID 62 | 'Server' = $Domain 63 | 'Enabled' = $false 64 | } 65 | 66 | if ($Description -ne ' ') {$SetParms.Add('Description',$Description)} 67 | if ($PSCredential) {$SetParms.Add('Credential',$PSCredential)} 68 | 69 | Write-Verbose -Message "Disabling $ID" 70 | 71 | Set-ADUser @SetParms 72 | 73 | if ($DisabledOU){ 74 | 75 | $MoveParms = @{ 76 | 'Identity' = $($UserInfo.DistinguishedName) 77 | 'TargetPath' = $DisabledOU 78 | 'Server' = $Domain 79 | } 80 | if ($PSCredential) {$MoveParms.Add('Credential',$PSCredential)} 81 | 82 | Write-Verbose -Message "Moving $ID to $DisabledOU" 83 | 84 | Move-ADObject @MoveParms 85 | } 86 | 87 | } 88 | Catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException]{ 89 | Write-Warning -Message "$Identity was not found" 90 | Write-Output -InputObject $Identity | Out-File $ErrorLog 91 | } 92 | Catch { 93 | Write-Warning -Message $_.Exception.Message 94 | } 95 | } 96 | } 97 | END { 98 | Write-Verbose -Message "Finished" 99 | } 100 | } -------------------------------------------------------------------------------- /Functions/Empty-IADComputersContainer.ps1: -------------------------------------------------------------------------------- 1 | Function Empty-IADComputersContainer{ 2 | <# 3 | .SYNOPSIS 4 | Moves either or both Workstation and Server computer accounts to the specified Active Directory OUs from the Computers container. 5 | .DESCRIPTION 6 | Empty-IADComputersContainer queries the specified domain, gathers all computer accounts inside the Computers container, and moves them to the Active Directory paths provided by operator. Suggested application of this function is to use it inside a daily automated task to ensure a more organized Active Directory. Please note: moving devices to different OUs will apply any Group Policy Objects linked. 7 | .PARAMETER Server 8 | Specifies the Active Directory Domain Services instance to connect to. 9 | .PARAMETER Credential 10 | Specifies the credentials used to move the objects. Functions the same way as Active Directory cmdlets (PSCredential). 11 | .PARAMETER IncludeWorkstations 12 | Use this SwitchParameter to specify you want to move workstations. Workstation operating systems begin with Windows 7, 8, 10, or XP. 13 | .PARAMETER WorkstationOU 14 | Specifies the target organizational unit to move the workstation objects to. This parameter accepts the distinguishedname of the OU as a string. 15 | .PARAMETER IncludeServers 16 | Use this SwitchParameter to specify you want to move servers. Server operating systems begin with Windows Server. 17 | .PARAMETER ServerOU 18 | Specifies the target organizational unit to move the server objects to. This parameter accepts the distinguishedname of the OU as a string. 19 | .PARAMETER WhatIf 20 | Supports the SwitchParameter WhatIf. If specified the function will return what would happen if it was ran, taking no action. Use this to see what accounts are targeted without actually moving them. 21 | .PARAMETER Confirm 22 | Supports the SwitchParameter Confirm. If specified the function will ask for confirmation before moving each account. If you do not specify -Confirm it will move the objects without asking. 23 | .EXAMPLE 24 | Empty-IADComputersContainer -Server fabrikom.com -Credential (Get-Credential) -IncludeWorkstations -IncludeServers -WorkstationOU "OU=Workstations,DC=fabrikom,DC=com" -ServerOU "OU=Servers,DC=fabrikom,DC=com" -WhatIf 25 | 26 | Queries the fabrikom.com domain after prompting for credentials to use for movement. Returns what will happen (-WhatIf) and won't take any actions. 27 | .EXAMPLE 28 | Empty-IADComputersContainer -Server fabrikom.com -Credential $Creds -IncludeServers -ServerOU "OU=Servers,DC=fabrikom,DC=com" 29 | 30 | Queries the currently joined domain and moves servers only using credentials stored inside the $Creds PSCredential object. 31 | #> 32 | [CmdletBinding()] 33 | param([string]$Server, 34 | [System.Management.Automation.PSCredential]$Credential, 35 | [switch]$IncludeWorkstations, 36 | [string]$WorkstationOU, 37 | [switch]$IncludeServers, 38 | [string]$ServerOU, 39 | [switch]$Confirm, 40 | [switch]$WhatIf) 41 | 42 | $ReturnList = @() 43 | 44 | if($IncludeWorkstations -or $IncludeServers){ 45 | 46 | #Build the SearchBase for the Computers container 47 | $SearchBase = "CN=Computers," + "$((Get-ADDomain -Server $Server).distinguishedname)" 48 | 49 | #Process Workstations 50 | if($IncludeWorkstations){ 51 | 52 | $Workstations = Get-ADComputer -Server $Server -Searchbase $Searchbase -filter{operatingsystem -like "Windows 7*" -or operatingsystem -like "Windows XP*" -or operatingsystem -like "Windows 8*" -or operatingsystem -like "Windows 10*"} 53 | 54 | foreach($Workstation in $Workstations){ 55 | 56 | Try{ 57 | Move-ADObject -Identity $Workstation -Server $Server -TargetPath $WorkstationOU -Credential $Credential -Confirm:$Confirm -Whatif:$WhatIf -Verbose 58 | 59 | $A = [pscustomobject]@{"Computer"=$Workstation.dnshostname; 60 | "Type"="Workstation"; 61 | "Status"="Successful"} 62 | } 63 | 64 | Catch{ 65 | $A = [pscustomobject]@{"Computer"=$Workstation.dnshostname; 66 | "Type"="Workstation"; 67 | "Status"="Failed"; 68 | "Error"="$Error[0]"} 69 | } 70 | 71 | $ReturnList += $A 72 | 73 | } 74 | } 75 | 76 | #Process Servers 77 | if($IncludeServers){ 78 | 79 | $Servers = Get-ADComputer -Server $Server -SearchBase $SearchBase -filter{operatingsystem -like "Windows Server*"} 80 | 81 | foreach($ServerInstance in $Servers){ 82 | 83 | Try{ 84 | Move-ADObject -Identity $ServerInstance -Server $Server -TargetPath $ServerOU -Credential $Credential -Confirm:$Confirm -Whatif:$WhatIf -Verbose 85 | 86 | $A = [pscustomobject]@{"Computer"=$ServerInstance.dnshostname; 87 | "Type"="Server"; 88 | "Status"="Successful"} 89 | } 90 | 91 | Catch{ 92 | $A = [pscustomobject]@{"Computer"=$ServerInstance.dnshostname; 93 | "Type"="Server"; 94 | "Status"="Failed"; 95 | "Error"="$Error[0]"} 96 | } 97 | 98 | $ReturnList += $A 99 | 100 | } 101 | } 102 | 103 | 104 | } 105 | 106 | else{Write-host "Please specify -IncludeWorkstations or -IncludeServers when using this cmdlet"} 107 | 108 | return $ReturnList 109 | 110 | } -------------------------------------------------------------------------------- /Functions/Get-IADGroupMember.ps1: -------------------------------------------------------------------------------- 1 | function Get-IADGroupMember 2 | { 3 | <# 4 | .SYNOPSIS 5 | Gets the members of an Active Directory group. 6 | .DESCRIPTION 7 | Get-IADGroupMember gets the members of an Active Directory group. Members include users, groups, computers and foreignSecurityPrincipal objects. 8 | It improves upon the Get-ADGroup cmdlet by supporting cross forest direct and nested memberships as well as the ability to report back foreignSecurityPrincipal 9 | or "broken SIDS" objects. 10 | .PARAMETER Identity 11 | Specifies an Active Directory object by GUID, DistinguishedName, objectSID, or SamAccountName. 12 | .PARAMETER Server 13 | Specifies the Active Directory Domain Services instance to connect to. 14 | .PARAMETER Recursive 15 | Specifies that the cmdlet report all nested groups and group memberships. 16 | .EXAMPLE 17 | Get-IADGroupMember -Identity Group1 18 | .EXAMPLE 19 | Get-IADGroupMember -Identity Group1 -Server Globomantics.com 20 | .EXAMPLE 21 | Get-IADGroupMember -Identity Group1 -Server Globomantics.com -Recursive 22 | #> 23 | [CmdletBinding()] 24 | [Alias()] 25 | Param 26 | ( 27 | [Parameter(Mandatory=$true,Position=0)] 28 | [string]$Identity, 29 | [string]$Server, 30 | [switch]$Recursive 31 | ) 32 | 33 | Begin 34 | { 35 | $splat = @{ 36 | Identity = $Identity 37 | } 38 | 39 | if ($PSBoundParameters.ContainsKey('Server')){ 40 | $splat.Add('Server',$Server) 41 | } 42 | 43 | } 44 | Process 45 | { 46 | if ($Recursive){ 47 | [IADGroup]::new($splat).NestedMembers() 48 | } else { 49 | [IADGroup]::new($splat).DirectMembers() 50 | } 51 | } 52 | End 53 | { 54 | } 55 | } -------------------------------------------------------------------------------- /Functions/Get-IADUser.ps1: -------------------------------------------------------------------------------- 1 | function Get-IADUser 2 | { 3 | [CmdletBinding()] 4 | Param 5 | ( 6 | [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,Position=0)] 7 | [string[]]$Identity 8 | ) 9 | 10 | Begin 11 | { 12 | } 13 | Process { 14 | 15 | foreach ($User in $Identity) { 16 | Start-RSJob -Name $User -Scriptblock {Get-ADUser -Identity $Using:User} | Out-Null 17 | } 18 | } 19 | End 20 | { 21 | Get-RSJob | Receive-RSJob 22 | #Get-RSjob | Remove-RSJob 23 | } 24 | } -------------------------------------------------------------------------------- /Functions/Move-IADDisabledComputers.ps1: -------------------------------------------------------------------------------- 1 | Function Move-IADDisabledComputers{ 2 | <# 3 | .SYNOPSIS 4 | Moves all disabled computer accounts found inside a domain to the specified OU for disabled computers. 5 | .DESCRIPTION 6 | Move-IADDisabledComputers queries the specified domain, gathers all disabled computer accounts, and moves them to the Active Directory path provided by operator. Suggested application of this function is to use it inside a daily automated task to ensure a more organized Active Directory. 7 | .PARAMETER Server 8 | Specifies the Active Directory Domain Services instance to connect to. 9 | .PARAMETER Credential 10 | Specifies the credentials used to move the objects. Functions the same way as Active Directory cmdlets (PSCredential). 11 | .PARAMETER DisabledOU 12 | Specifies the target organizational unit to move the objects to. This parameter accepts the distinguishedname of the OU as a string. 13 | .PARAMETER WhatIf 14 | Supports the SwitchParameter WhatIf. If specified the function will return what would happen if it was ran, taking no action. Use this to see what accounts are targeted without actually moving them. 15 | .PARAMETER Confirm 16 | Supports the SwitchParameter Confirm. If specified the function will ask for confirmation before moving each account. If you do not specify -Confirm it will move the objects without asking. 17 | .EXAMPLE 18 | Move-IADDisabledComputers -Server fabrikom.com -Credential (get-credential) -DisabledOU "OU=Disabled,DC=fabrikom,DC=com" -Confirm 19 | 20 | Queries the fabrikom.com domain after prompting for credentials to use. Will ask for confirmation before moving to the Disabled OU specified. 21 | .EXAMPLE 22 | Move-IADDisabledComputers -Credential $Creds -DisabledOU "OU=Disabled,DC=fabrikom,DC=com" -WhatIf 23 | 24 | Queries the currently joined domain using credentials stored inside the $Creds PSCredential object and returns what will happen, but does not take action (-WhatIf). 25 | #> 26 | [CmdletBinding()] 27 | param([string]$Server, 28 | [System.Management.Automation.PSCredential]$Credential, 29 | [Parameter(Mandatory=$true)] 30 | [string]$DisabledOU, 31 | [switch]$Confirm, 32 | [switch]$WhatIf) 33 | 34 | $ReturnList = @() 35 | 36 | #Gather the computer objects that are disabled and not inside the $DisabledOU 37 | $DisabledComputers = Get-ADComputer -Server $Server -Filter {enabled -eq $false} | Where-Object {$_.distinguishedname -notlike "*$DisabledOU*"} 38 | 39 | 40 | #Move each computer account to the $DisabledOU 41 | if($DisabledComputers){ 42 | foreach($Computer in $DisabledComputers){ 43 | 44 | Try{ 45 | Move-ADObject -Server $Server -Identity $Computer -TargetPath $DisabledOU -Credential $Credential -Confirm:$Confirm -Whatif:$WhatIf -Verbose 46 | $A = [pscustomobject]@{"Computer"=$Computer.dnshostname; 47 | "Status"="Successful"} 48 | } 49 | 50 | Catch{ 51 | $A = [pscustomobject]@{"Computer"=$Computer.dnshostname; 52 | "Status"="Failure"; 53 | "Error"=$Error[0]} 54 | } 55 | 56 | $ReturnList += $A 57 | } 58 | } 59 | 60 | else{$ReturnList = "No computers found"} 61 | 62 | Return $ReturnList 63 | 64 | } -------------------------------------------------------------------------------- /Functions/Move-IADDisabledUsers.ps1: -------------------------------------------------------------------------------- 1 | Function Move-IADDisabledUsers{ 2 | <# 3 | .SYNOPSIS 4 | Moves all disabled user accounts found inside a domain to the specified OU for disabled users. 5 | .DESCRIPTION 6 | Move-IADDisabledUsers queries the specified domain, gathers all disabled user accounts, and moves them to the Active Directory path provided by operator. Suggested application of this function is to use it inside a daily automated task to ensure a more organized Active Directory. 7 | .PARAMETER Server 8 | Specifies the Active Directory Domain Services instance to connect to. 9 | .PARAMETER Credential 10 | Specifies the credentials used to move the objects. Functions the same way as Active Directory cmdlets (PSCredential). 11 | .PARAMETER DisabledOU 12 | Specifies the target organizational unit to move the objects to. This parameter accepts the distinguishedname of the OU as a string. 13 | .PARAMETER ExclusionList 14 | Specify which accounts if any need to be excluded from the move. If you have disabled system or service accounts for example that must remain in their current OU this will exclude them. The parameter accepts a string array of samaccountnames. 15 | .PARAMETER WhatIf 16 | Supports the SwitchParameter WhatIf. If specified the function will return what would happen if it was ran, taking no action. Use this to see what accounts are targeted without actually moving them. 17 | .PARAMETER Confirm 18 | Supports the SwitchParameter Confirm. If specified the function will ask for confirmation before moving each account. If you do not specify -Confirm it will move the objects without asking. 19 | .EXAMPLE 20 | Move-IADDisabledUsers -Server fabrikom.com -Credential (get-credential) -DisabledOU "OU=Disabled,DC=fabrikom,DC=com" -ExclusionList test1,test2,test3 -Confirm 21 | 22 | Queries the fabrikom.com domain after prompting for credentials to use. Will ask for confirmation before moving to the Disabled OU specified and excludes user accounts test1, test2, and test3. 23 | .EXAMPLE 24 | Move-IADDisabledUsers -Credential $Creds -DisabledOU "OU=Disabled,DC=fabrikom,DC=com" -WhatIf 25 | 26 | Queries the currently joined domain using credentials stored inside the $Creds PSCredential object and returns what will happen, but does not take action (-WhatIf). 27 | #> 28 | [CmdletBinding()] 29 | param([string]$Server, 30 | [System.Management.Automation.PSCredential]$Credential, 31 | [Parameter(Mandatory=$true)] 32 | [string]$DisabledOU, 33 | [string[]]$ExclusionList, 34 | [switch]$Confirm, 35 | [switch]$WhatIf) 36 | 37 | $FilterExclusionList = "" 38 | $ReturnList = @() 39 | 40 | #Build the string for the filter exclusion list 41 | foreach($Account in $ExclusionList){$FilterExclusionList += " -and samaccountname -notlike `"$Account`""} 42 | $FilterString = "enabled -eq `$false -and samaccountname -notlike `"krbtgt`" -and samaccountname -notlike `"Guest`" -and samaccountname -notlike `"DefaultAccount`"$FilterExclusionList" 43 | 44 | #Gather the user objects that are disabled and not inside the $DisabledOU or $ExclusionList 45 | $DisabledUsers = Get-ADUser -Server $Server -Filter $FilterString | Where-Object {$_.distinguishedname -notlike "*$DisabledOU*"} 46 | 47 | 48 | #Move each user account to the $DisabledOU 49 | if($DisabledUsers){ 50 | foreach($User in $DisabledUsers){ 51 | 52 | Try{ 53 | Move-ADObject -Server $Server -Identity $User -TargetPath $DisabledOU -Credential $Credential -Confirm:$Confirm -Whatif:$WhatIf -Verbose 54 | $A = [pscustomobject]@{"User"=$User.samaccountname; 55 | "Status"="Successful"} 56 | } 57 | 58 | Catch{ 59 | $A = [pscustomobject]@{"User"=$User.samaccountname; 60 | "Status"="Failure"; 61 | "Error"=$Error[0]} 62 | } 63 | 64 | $ReturnList += $A 65 | } 66 | } 67 | 68 | else{$ReturnList = "No users found"} 69 | 70 | Return $ReturnList 71 | 72 | } -------------------------------------------------------------------------------- /Functions/Move-IADEnabledComputers.ps1: -------------------------------------------------------------------------------- 1 | Function Move-IADEnabledComputers{ 2 | <# 3 | .SYNOPSIS 4 | Moves all enabled computer accounts found inside the specified disabled OU for the domain to the specified target OU 5 | .DESCRIPTION 6 | Move-IADEnabledComputers queries the specified domain, gathers all enabled computer accounts inside the specified Disabled OU, and moves them to the Active Directory paths provided by operator. Suggested application of this function is to use it inside a daily automated task to ensure a more organized Active Directory. 7 | .PARAMETER Server 8 | Specifies the Active Directory Domain Services instance to connect to. 9 | .PARAMETER Credential 10 | Specifies the credentials used to move the objects. Functions the same way as Active Directory cmdlets (PSCredential). 11 | .PARAMETER DisabledOU 12 | Specifies the disabled objects organizational unit to query. This parameter accepts the distinguishedname of the OU as a string. 13 | .PARAMETER TargetDesktopOU 14 | Specifies the Desktop organizational unit to move workstations into. This parameter accepts the distinguishedname of the OU as a string. (Windows 7*, 8*, 10*, XP*) 15 | .PARAMETER TargetServerOU 16 | Specifies the Server organizational unit to move servers into. This parameter accepts the distinguishedname of the OU as a string. (Windows Server*) 17 | .PARAMETER WhatIf 18 | Supports the SwitchParameter WhatIf. If specified the function will return what would happen if it was ran, taking no action. Use this to see what accounts are targeted without actually moving them. 19 | .PARAMETER Confirm 20 | Supports the SwitchParameter Confirm. If specified the function will ask for confirmation before moving each account. If you do not specify -Confirm it will move the objects without asking. 21 | .EXAMPLE 22 | Move-IADEnabledComputers -Server fabrikom.com -Credential (get-credential) -DisabledOU "OU=Disabled,DC=fabrikom,DC=com" -TargetDesktopOU "OU=Workstations",DC=fabrikom,DC=com" -TargetServerOU "OU=Server,DC=fabrikom,DC=com" 23 | 24 | Queries the fabrikom.com domain after prompting for credentials to use. Moves any returned accounts to their respective target OUs. 25 | .EXAMPLE 26 | Move-IADEnabledComputers -Server fabrikom.com -Credential (get-credential) -DisabledOU "OU=Disabled,DC=fabrikom,DC=com" -TargetDesktopOU "OU=Workstations",DC=fabrikom,DC=com" -TargetServerOU "OU=Server,DC=fabrikom,DC=com" -WhatIf 27 | 28 | Queries the fabrikom.com domain after prompting for credentials to use. Returns what will happen, but does not take action (-WhatIf). 29 | #> 30 | [CmdletBinding()] 31 | param([string]$Server, 32 | [System.Management.Automation.PSCredential]$Credential, 33 | [Parameter(Mandatory=$true)] 34 | [string]$DisabledOU, 35 | [string]$TargetDesktopOU, 36 | [string]$TargetServerOU, 37 | [switch]$Confirm, 38 | [switch]$WhatIf) 39 | 40 | $ReturnList = @() 41 | 42 | if(!$TargetDesktopOU -and !$TargetServerOU){throw "You must specify either a Target Destop or Server OU"} 43 | 44 | #Gather the computer objects that are enabled and inside the $DisabledOU 45 | $EnabledComputers = Get-ADComputer -Server $Server -Filter {enabled -eq $true} -properties operatingsystem,dnshostname | Where-Object {$_.distinguishedname -like "*$DisabledOU*"} 46 | 47 | #Move each computer account to the $TargetPath 48 | if($EnabledComputers){ 49 | foreach($Computer in $EnabledComputers){ 50 | 51 | #If Desktop use TargetDesktopOU 52 | if($Computer.operatingsystem -like "Windows 7*" -or $Computer.operatingsystem -like "Windows 8*" ` 53 | -or $Computer.operatingsystem -like "Windows XP*" -or $Computer.operatingsystem -like "Windows 10*"){$TargetPath = $TargetDesktopOU} 54 | 55 | #If Server use TargetServerOU 56 | if($Computer.operatingsystem -like "Windows Server*"){$TargetPath = $TargetServerOU} 57 | 58 | Try{ 59 | Move-ADObject -Server $Server -Identity $Computer -TargetPath $TargetPath -Credential $Credential -Confirm:$Confirm -Whatif:$WhatIf -Verbose 60 | $A = [pscustomobject]@{"Computer"=$Computer.dnshostname; 61 | "Status"="Successful"} 62 | } 63 | 64 | Catch{ 65 | $A = [pscustomobject]@{"Computer"=$Computer.dnshostname; 66 | "Status"="Failure"; 67 | "Error"=$Error[0]} 68 | } 69 | 70 | $ReturnList += $A 71 | } 72 | } 73 | 74 | else{$ReturnList = "No computers found"} 75 | 76 | Return $ReturnList 77 | 78 | } -------------------------------------------------------------------------------- /Functions/Move-IADEnabledUsers.ps1: -------------------------------------------------------------------------------- 1 | Function Move-IADEnabledUsers{ 2 | <# 3 | .SYNOPSIS 4 | Moves all enabled user accounts found inside the specified disabled OU for the domain to the specified target OU 5 | .DESCRIPTION 6 | Move-IADEnabledUsers queries the specified domain, gathers all enabled user accounts inside the specified Disabled OU, and moves them to the Active Directory path provided by operator. Suggested application of this function is to use it inside a daily automated task to ensure a more organized Active Directory. 7 | .PARAMETER Server 8 | Specifies the Active Directory Domain Services instance to connect to. 9 | .PARAMETER Credential 10 | Specifies the credentials used to move the objects. Functions the same way as Active Directory cmdlets (PSCredential). 11 | .PARAMETER DisabledOU 12 | Specifies the disabled objects organizational unit to query. This parameter accepts the distinguishedname of the OU as a string. 13 | .PARAMETER TargetOU 14 | Specifies the User organizational unit to move enabled users into. This parameter accepts the distinguishedname of the OU as a string. 15 | .PARAMETER WhatIf 16 | Supports the SwitchParameter WhatIf. If specified the function will return what would happen if it was ran, taking no action. Use this to see what accounts are targeted without actually moving them. 17 | .PARAMETER Confirm 18 | Supports the SwitchParameter Confirm. If specified the function will ask for confirmation before moving each account. If you do not specify -Confirm it will move the objects without asking. 19 | .EXAMPLE 20 | Move-IADEnabledUsers -Server fabrikom.com -Credential (get-credential) -DisabledOU "OU=Disabled,DC=fabrikom,DC=com" -TargetOU "OU=UserAccounts",DC=fabrikom,DC=com" 21 | 22 | Queries the fabrikom.com domain after prompting for credentials to use. Moves any returned accounts to the respective target OU. 23 | .EXAMPLE 24 | Move-IADEnabledUsers -Server fabrikom.com -Credential (get-credential) -DisabledOU "OU=Disabled,DC=fabrikom,DC=com" -TargetOU "OU=UserAccounts",DC=fabrikom,DC=com" -WhatIf 25 | 26 | Queries the fabrikom.com domain after prompting for credentials to use. Returns what will happen, but does not take action (-WhatIf). 27 | #> 28 | [CmdletBinding()] 29 | param([string]$Server, 30 | [System.Management.Automation.PSCredential]$Credential, 31 | [Parameter(Mandatory=$true)] 32 | [string]$DisabledOU, 33 | [string]$TargetOU, 34 | [switch]$Confirm, 35 | [switch]$WhatIf) 36 | 37 | $ReturnList = @() 38 | 39 | #Gather the user objects that are enabled and inside the $DisabledOU 40 | $EnabledUsers = Get-ADUser -Server $Server -Filter {enabled -eq $true} | Where-Object {$_.distinguishedname -like "*$DisabledOU*"} 41 | 42 | #Move each user account to the $TargetOU 43 | if($EnabledUsers){ 44 | foreach($User in $EnabledUsers){ 45 | 46 | 47 | Try{ 48 | Move-ADObject -Server $Server -Identity $CUser -TargetPath $TargetOU -Credential $Credential -Confirm:$Confirm -Whatif:$WhatIf -Verbose 49 | $A = [pscustomobject]@{"User"=$User.samaccountname; 50 | "Status"="Successful"} 51 | } 52 | 53 | Catch{ 54 | $A = [pscustomobject]@{"User"=$User.samaccountname; 55 | "Status"="Failure"; 56 | "Error"=$Error[0]} 57 | } 58 | 59 | $ReturnList += $A 60 | } 61 | } 62 | 63 | else{$ReturnList = "No users found"} 64 | 65 | Return $ReturnList 66 | 67 | } -------------------------------------------------------------------------------- /ImprovedActiveDirectory.psd1: -------------------------------------------------------------------------------- 1 | # 2 | # Module manifest for module 'moduleManifest-c3476a47-01ee-40cd-a33d-bd3ca861771f' 3 | # 4 | # Generated by: Josh Duffney 5 | # 6 | # Generated on: 9/8/2016 7 | # 8 | 9 | @{ 10 | 11 | # Script module or binary module file associated with this manifest. 12 | RootModule = 'ImprovedActiveDirectory.psm1' 13 | 14 | # Version number of this module. 15 | ModuleVersion = '1.0.0' 16 | 17 | # Supported PSEditions 18 | # CompatiblePSEditions = @() 19 | 20 | # ID used to uniquely identify this module 21 | GUID = 'd7053614-8655-44ff-bce8-ad9f4ca86475' 22 | 23 | # Author of this module 24 | Author = 'Josh Duffney' 25 | 26 | # Company or vendor of this module 27 | CompanyName = 'Unknown' 28 | 29 | # Copyright statement for this module 30 | Copyright = '(c) 2016 Josh Duffney. All rights reserved.' 31 | 32 | # Description of the functionality provided by this module 33 | Description = 'PowerShell module with improved ActiveDirectory cmdlets' 34 | 35 | # Minimum version of the Windows PowerShell engine required by this module 36 | # PowerShellVersion = '' 37 | 38 | # Name of the Windows PowerShell host required by this module 39 | # PowerShellHostName = '' 40 | 41 | # Minimum version of the Windows PowerShell host required by this module 42 | # PowerShellHostVersion = '' 43 | 44 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 45 | # DotNetFrameworkVersion = '' 46 | 47 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. 48 | # CLRVersion = '' 49 | 50 | # Processor architecture (None, X86, Amd64) required by this module 51 | # ProcessorArchitecture = '' 52 | 53 | # Modules that must be imported into the global environment prior to importing this module 54 | # RequiredModules = @() 55 | 56 | # Assemblies that must be loaded prior to importing this module 57 | # RequiredAssemblies = @() 58 | 59 | # Script files (.ps1) that are run in the caller's environment prior to importing this module. 60 | # ScriptsToProcess = @() 61 | 62 | # Type files (.ps1xml) to be loaded when importing this module 63 | # TypesToProcess = @() 64 | 65 | # Format files (.ps1xml) to be loaded when importing this module 66 | # FormatsToProcess = @() 67 | 68 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess 69 | # NestedModules = @() 70 | 71 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. 72 | FunctionsToExport = '*' 73 | 74 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. 75 | CmdletsToExport = '*' 76 | 77 | # Variables to export from this module 78 | VariablesToExport = '*' 79 | 80 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. 81 | AliasesToExport = '*' 82 | 83 | # DSC resources to export from this module 84 | # DscResourcesToExport = @() 85 | 86 | # List of all modules packaged with this module 87 | # ModuleList = @() 88 | 89 | # List of all files packaged with this module 90 | # FileList = @() 91 | 92 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. 93 | PrivateData = @{ 94 | 95 | PSData = @{ 96 | 97 | # Tags applied to this module. These help with module discovery in online galleries. 98 | # Tags = @() 99 | 100 | # A URL to the license for this module. 101 | # LicenseUri = '' 102 | 103 | # A URL to the main website for this project. 104 | # ProjectUri = '' 105 | 106 | # A URL to an icon representing this module. 107 | # IconUri = '' 108 | 109 | # ReleaseNotes of this module 110 | # ReleaseNotes = '' 111 | 112 | } # End of PSData hashtable 113 | 114 | } # End of PrivateData hashtable 115 | 116 | # HelpInfo URI of this module 117 | # HelpInfoURI = '' 118 | 119 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. 120 | # DefaultCommandPrefix = '' 121 | 122 | } 123 | 124 | 125 | -------------------------------------------------------------------------------- /ImprovedActiveDirectory.psm1: -------------------------------------------------------------------------------- 1 | try { 2 | Import-Module ActiveDirectory 3 | } 4 | catch [System.Management.Automation.ParameterBindingException] { 5 | Write-Error -Message 'ActiveDirectory Module not found' -ErrorAction Stop 6 | } 7 | 8 | 9 | . $PSScriptRoot\Classes\IADGroup.ps1 10 | . $PSScriptRoot\Functions\Get-IADGroupMember.ps1 11 | . $PSScriptRoot\Functions\Disable-IADComputer.ps1 12 | . $PSScriptRoot\Functions\Disable-IADUser.ps1 13 | . $PSScriptRoot\Functions\ConvertTo-IADDomain.ps1 14 | . $PSScriptRoot\Functions\Move-IADDisabledUsers.ps1 15 | . $PSScriptRoot\Functions\Move-IADDisabledComputers.ps1 16 | . $PSScriptRoot\Functions\Move-IADEnabledComputers.ps1 17 | . $PSScriptRoot\Functions\Move-IADEnabledUsers.ps1 18 | . $PSScriptRoot\Functions\Empty-IADComputersContainer.ps1 19 | . $PSScriptRoot\Functions\Disable-IADInactiveComputers.ps1 20 | . $PSScriptRoot\Functions\Add-IADOUUsersToGroups.ps1 21 | 22 | Export-ModuleMember ConvertTo-IADDomain 23 | Export-ModuleMember Get-IADGroupMember 24 | Export-ModuleMember Disable-ADComputer 25 | Export-ModuleMember Disable-ADUser 26 | Export-ModuleMember Move-IADDisabledUsers 27 | Export-ModuleMember Move-IADDisabledComputers 28 | Export-ModuleMember Move-IADEnabledComputers 29 | Export-ModuleMember Move-IADEnabledUsers 30 | Export-ModuleMember Empty-IADComputersContainer 31 | Export-ModuleMember Disable-IADInactiveComputers 32 | Export-ModuleMember Add-IADOUUsersToGroups -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Joshua Duffney 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![improvedactivedirectory](http://i.imgur.com/EYLc36h.png "improvedactivedirectory") 2 | 3 | ## Introduction 4 | ImprovedActiveDirectory is a PowerShell module that builds on and expands upon the ActiveDirectory module used for interacting with ActiveDirectory domains and forests. 5 | The purpose of this module is to provide richer and more consistent experience for ActiveDirectory engineers that are automating the maintenance and administration of 6 | ActiveDirectory. To do that it combines several existing cmdlets to perform administration tasks as well as improved upon those cmdlets with advanced PowerShell scripting 7 | techniques. 8 | 9 | ## Requirements 10 | 11 | - PowerShell Version 5.0+ 12 | - [ActiveDirectory Module](https://www.microsoft.com/en-us/download/details.aspx?id=45520) 13 | 14 | ### Installation 15 | 16 | 1. [Download the module](https://github.com/Duffney/ImprovedActiveDirectory/archive/master.zip) 17 | 2. Unblock the .zip file 18 | 3. Extract ImprovedActiveDirectory-master.zip 19 | 4. Rename ImprovedActiveDirectory-master to ImprovedActiveDirectory 20 | 5. Copy ImprovedActiveDirectory to *C:\Program Files\WindowsPowerShell\Modules* 21 | 6. Open PowerShell 22 | 7. *Import-Module ImprovedActiveDirectory* 23 | 24 | ### Cmdlets 25 | 26 | - Get-IADGroupMember 27 | - Disable-IADComputer 28 | - Disable-IADUser 29 | - ConvertTo-IADDomain 30 | - Move-IADDisabledUsers 31 | - Move-IADDisabledComputers 32 | - Empty-IADComputersContainer 33 | - Disable-IADInactiveComputers 34 | 35 | ### Contributors 36 | 37 | [Josh Duffney](https://github.com/Duffney) 38 | 39 | [Nathan Foreman](https://github.com/foremann) 40 | 41 | 42 | -------------------------------------------------------------------------------- /Tests/ConvertTo-IADDoman.tests.ps1: -------------------------------------------------------------------------------- 1 | # Get the path the script is executing from 2 | $here = Split-Path -Parent $MyInvocation.MyCommand.Path 3 | 4 | # If the module is already in memory, remove it 5 | Get-Module ImprovedActiveDirectory | Remove-Module -Force 6 | 7 | # Import the module from the local path, not from the users Documents folder 8 | Import-Module $PSScriptRoot\..\ImprovedActiveDirectory.psm1 -Force 9 | 10 | Describe 'ConvertTo-IADDomain Tests' { 11 | 12 | It 'module should be loaded' { 13 | "$PSScriptRoot\..\ImprovedActiveDirectory.psm1" | should exist 14 | } 15 | 16 | It 'outputs valid domain name' { 17 | ConvertTo-IADDomain -distinguishedname 'CN=Administrator,CN=Users,DC=wef,DC=com','CN=Administrator,CN=Users,DC=wef,DC=com' | should match '[a-z]+\.[a-z]+\.[a-z]+|[a-z]+\.[a-z]+' 18 | } 19 | 20 | It 'reject invalid distinguishedname' { 21 | ConvertTo-IADDomain -distinguishedname 'CN=Administrator,CN=Users,DC=wefasdfasdfasdfadsfasdfasdf,DC=com' | should throw 22 | } 23 | } -------------------------------------------------------------------------------- /Tests/ImprovedActiveDirectory.Tests.ps1: -------------------------------------------------------------------------------- 1 | $ModuleManifestName = 'ImprovedActiveDirectory.psd1' 2 | # f6497b70-2bfe-4a91-bd45-ccd2f2ba28fd - testing use of PLASTER predefined variables. 3 | Import-Module $PSScriptRoot\..\$ModuleManifestName 4 | 5 | Describe 'Module Manifest Tests' { 6 | It 'Passes Test-ModuleManifest' { 7 | Test-ModuleManifest -Path $PSScriptRoot\..\$ModuleManifestName 8 | $? | Should Be $true 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /en-US/about_ImprovedActiveDirectory.help.txt: -------------------------------------------------------------------------------- 1 | TOPIC 2 | ImprovedActiveDirectory 1.0.0 3 | 4 | SHORT DESCRIPTION 5 | You should considering providing an introduction and overview of your 6 | module here. 7 | 8 | LONG DESCRIPTION 9 | Discuss what the "primary" commands are in your module especially if 10 | there are many commands. Discuss how to get started using this module 11 | providing examples where appropriate. 12 | 13 | YOUR HEADER HERE 14 | About topics in PowerShell are free-form text. Add headers to your 15 | about topic as necessary. 16 | --------------------------------------------------------------------------------