Saturday, December 11, 2021

Automating Server Maintenance - C:\Users And The Dearly Departed



 So, it's not an uncommon thing in a large organization, especially where there are consultants or professional service engagements where there is a congregating effect on the C:\Users folder where users come and go, but the data remains. If we're looking at a Jump Server (a server that is local to a collection of other servers) often you'll find that that folder will have an archive of useless folders for the ancestors of the organization and when your C: drive is running low on space determining who is no longer with us, BillG rest their LinkedIn profile.

So, I got to thinking about how to make this simple, automated, and painless. How to report, or even better, clear the folders of C:\Users folder of old accounts. Let's fire up an Interactive Scripting Environment like Windows PowerShell ISE:

or Visual Studio Code:

... and give it a spin. I'm going to assume the PowerShell ISE is used because it's a default and always available.

The Basics

Based on Active Directory and Powershell's ability to converse in fluent AD the Get-ADUser commandlet allows us to get an active user list:

$ActiveUsers = $(Get-ADUser -Filter *).SamAccountName

Now, sometimes the commandlet needs some help, a Windows feature to be installed, so if this doesn't work try this:

Import-Module ServerManager

Add-WindowsFeature RSAT-AD-PowerShell

That should do the job and we can move on. 

Try it. Copy/Paste or enter the following into the ISE and hit F5 (run):

$activeUsers = $(Get-ADUser -Filter *).SamAccountName

$activeUsers

If you're on a computer that is an Active Directory member Windows system, this should produce a list of user names, short names. This process causes the biggest delay, especially if the domain controller is over a WAN connection.

The next thing we need is a list of folders in C:\Users. This is a snap using:

$userFolders = $(Get-ChildItem -Path C:\Users).BaseName

You can try that too, but remember to add the line [$userFolders] line to display the output, then hit F5.

Note: To return to the Script view in the ISE, hit CTRL-R.

We now have the basics of the data we need to do the work.

Being Exceptional:

While defining variables is always a best practice, and I mostly do this, there's also value to adding some exclusions. Some folders need to be ignored, left alone for other purposes, so we'll ignore them using the variable $Exceptions:

$current = @()   # current users (keep)

$former = @()  # the dearly departed (to be removed)

$Exceptions = @()

$Exceptions += @("Administrator")

$Exceptions += @("Public")

Getting There

We'll need to spin through the list of folders, likely the shorter list is the folders collected into the userFolders array. We'll use a foreach loop to do that:

    foreach($folder in $userFolders){

We'll need to ignore the exceptions noted earlier using the contains operator:

    if(!($exceptions -contains $folder)){

We can re-use the logic to evaluate which accounts are current or former users too:

        if($activeUsers -contains $folder){

            $current += @($folder)

        } else {

            $former += @($folder)

        }

If the folder's name is contained in the array activeUsers the folder name is added to the current [users] array, otherwise, the folder name is added to the former [users] array.

The Output But Not The End

We can simply dump the results, which works as a To-Do list for the current IT intern to take care of:

write-host "Current Users' Folders:"

$current

write-host "`nNon-Current Users' Folders:"

$former

Or, perhaps we can script the removal of the user profiles using more PowerShell scripts. You will need to run the script under an account with sufficient AD rights, but you can work out whether that's a super-special service account or just something you do once a month, perhaps on the first of the month.

You can consider your next steps but here's some reading material (no warranties on this, it's not my site or post on Spiceworks.com):

The Code

$current = @() 

$former = @()


$Exceptions = @()

$Exceptions += @("Administrator")

$Exceptions += @("Public")


$ActiveUsers = $(Get-ADUser -Filter *).SamAccountName

$UserFolders = $(Get-ChildItem -Path C:\Users).BaseName


foreach($folder in $userFolders){

    if(!($Exceptions -contains $folder)){

        if($ActiveUsers -contains $folder){

            $current += @($folder)

        } else {

            $former += @($folder)

        }

    }

}


write-host "Current Users' Folders:"

$current

write-host "`nNon-Current Users' Folders:"

$former


Additional Reading

Active Directory Glossary - Terms and Fundamental Concepts - Active Directory Pro

No comments:

There is no individual ownership when you are part of a team, it's the sum of the parts that makes you the RESILIENT team you need to be.