Now we have a way to find the disable OU, and to disable a user, now it’s time to disable old accounts. We do this by targeting the Last Logon dates.

Word of warning before we continue. When you do this, target a single OU instead of all of the company. Target only enabled users as well. Targeting all of AD will cause you to disable service accounts and system accounts. This can cause your system to crash. Also, target enabled users as many companies us templates that are disabled.

Now we got the warning out of the way, lets get started. The code is very simple. The first step is to get the days back you want to go and find that date/time. We are going to us Get-Date and your input which we are calling $DaysBack.

$Time = (get-date).AddDays(-($DaysBack))

We get the Current date. Then we want to add days to that date, but backwards. So the (Get-Date) gives us the current date. Then .AddDays() will add the days. To make $DaysBack Negative, we simple multiple it by -1. if you completed algebra 1 in high school, you already see it. -($DaysBack) is the multiplication $DaysBack * -1.

Now we have the date we want to search the OU in question and get the users that haven’t log on since $DaysBack. We will do this with the simple Get-ADuser and the Where-Object commands.

$users = Get-aduser -Filter { Enabled -eq $true } -SearchBase $SearchOU -Properties LastLogondate | Where-Object {($_.LastLogonDate -le $Time) -and ($null -ne $_.LastLogonDate)}

We use the get-aduser filter to filter out everything that is enabled. Then we use the search base to search the OU we want to pull the information from. This saves us heartache of “oh crap I disabled my bosses test user.” Next, we pass it through the Where-object. We filter out everyone who last logon date that is less than or equal to the time we set earlier. We also search if nothing is not equal to the last logon date. We do this part because if an account hasn’t logged into the system yet, it will appear. Doing this avoids removing new hires on accident. Another note on the $null -ne $_.lastlogondate, it’s faster to search like this instead of $_.lastlogondate -ne $null. I don’t know why, but it is much faster.

Now we have a list of users who we need to disable, we just start up a for loop and disable them using the Disable-SHDUser.

foreach ($User in $users) {
     Disable-SHDUser -Username $user.samaccountname -OU $DisabledOU 
}

After the loop is done, it’s done. They are all disabled. But David, I want to see who was disabled! I agree. So I added a simple ShowResults switch for this loop. This is for those who need to see the results.

foreach ($User in $users) {
     Disable-SHDUser -Username $user.samaccountname -OU $DisabledOU
     if ($ShowResults) {
          Get-aduser -Identity $user.samaccountname -Properties LastLogonDate,Memberof | Select-Object DistinguishedName,Samaccountname,Name,Lastlogondate,Enabled,@{l="GroupCount";e={$_.memberof.count}}
     }
}

Combining functions in a module is a great way to get things done. These last two blogs should have shown this to you. Now, lets look at the script itself.

The Script

function invoke-SHDDisableInactiveUsers {
    [cmdletbinding()]
    param (
        [parameter(HelpMessage = "Days after", Mandatory = $True)][int]$DaysBack,
        [parameter(HelpMessage = "Moves to this OU if provided, If not, finds disable ou and moves it.")][string]$DisabledOU,
        [parameter(HelpMessage = "Moves to this OU if provided, If not, finds disable ou and moves it.", Mandatory = $true)][string]$SearchOU,
        [Parameter(HelpMessage = "Allows for custom Credential.")][System.Management.Automation.PSCredential]$Credential,
        [parameter(HelpMessage = "Show results")][switch]$ShowResults
    )
    $Time = (get-date).AddDays(-($DaysBack))
    if ($PSBoundParameters.ContainsKey('Credential')) {
        $users = Get-aduser -Filter { Enabled -eq $true } -Credential $Credential -SearchBase $SearchOU -Properties LastLogondate | Where-Object {($_.LastLogonDate -le $Time) -and ($null -ne $_.LastLogonDate)} | Sort-Object Samaccountname
        if ($PSBoundParameters.ContainsKey('DisabledOU')) {
            $DisabledOU = $DisabledOU
        }
        else {
            $DisabledOU = Find-SHDDisabledUsersOU -Credential $Credential
        }
        foreach ($User in $users) {
            Disable-SHDUser -Username $user.samaccountname -OU $DisabledOU -Credential $Credential 
            if ($ShowResults) {
                Get-aduser -Identity $user.samaccountname -Properties LastLogonDate,Memberof -Credential $Credential | Select-Object DistinguishedName,Samaccountname,Name,Lastlogondate,Enabled,@{l="GroupCount";e={$_.memberof.count}}
            }
        }
    }
    else {
        $users = Get-aduser -Filter { Enabled -eq $true } -SearchBase $SearchOU -Properties LastLogondate | Where-Object {($_.LastLogonDate -le $Time) -and ($null -ne $_.LastLogonDate)} | sort-object Samaccountname
        if ($PSBoundParameters.ContainsKey('OU')) {
            $DisabledOU = $DisabledOU
        }
        else {
            $DisabledOU = Find-SHDDisabledUsersOU
        }
        foreach ($User in $users) {
            Disable-SHDUser -Username $user.samaccountname -OU $DisabledOU
            if ($ShowResults) {
                Get-aduser -Identity $user.samaccountname -Properties LastLogonDate,Memberof | Select-Object DistinguishedName,Samaccountname,Name,Lastlogondate,Enabled,@{l="GroupCount";e={$_.memberof.count}}
            }
        }
    }
}

Next time I will explain the PSBoundParameters that you see in almost all scripts I run. It gives me the ability to give you the ability to have credentials but not require it.

If you have any questions, feel free to email me. These functions can be found on my git hub.