My 2nd PoSH script: Remove-Attributes.ps1

I have a requirement to clear some data duplicated in various user account attributes, in order to help shrink down the size of our AD database. The following script is what I’ve come up with. I would appreciate any constructive suggestions for optimization and bullet-proofing.

.\Remove-Attributes.ps1 -Filename inputfile.txt -Logfile outputfile.log []

.DESCRIPTION
    This script reads in a text file consisting of usernames and clears any
    deprecated object attribute fields that are not already NULL.
    This script can be run interactively or as a scheduled task, accepts a
    single filename as an argument and should run in any domain as long as the
    user has the proper credentials.

.PARAMETER Filename
    Name of filename containing user accounts to be modified

.PARAMETER Logfile
    Name of filename to save runtime messages
	
.EXAMPLES
    PS >.\Remove-Attributes.ps1 20160425-accounts.txt 20160425-accounts.log
#>

[CmdletBinding()]
Param(
	[Parameter(Mandatory=$True,Position=1)]
	$filename = $(throw "-Filename  is required."),
	[Parameter(Mandatory=$True,Position=2)]
	$logfile = $(throw "-LogFile  is required.")
)

function WriteLog($message)
{
	# Create a logfile entry with a timestamp and descriptive message
	# The -passthru switch simultaneously echos the message to the console
	$TimeStamp = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss');
	Add-Content $Logfile -value "$TimeStamp $message";# -passthru;
    return;
} # end function

function Main()
{
    $users = Get-Content -Path $filename;

    [string[]] $newAttrib = @();

    [string[]] $oldAttrib = @();

    ForEach ($user in $users)
    {
        For ($i = 0; $i -lt $newAttrib.Count; $i++)
        {
            $new = $newAttrib[$i];
            $old = $oldAttrib[$i];

            Try
            {
                [string]$new_result = Get-ADUser -Identity $user -Properties $new | Select -ExpandProperty $new;
                [string]$old_result = Get-ADUser -Identity $user -Properties $old | Select -ExpandProperty $old;
      
                If ([string]::IsNullOrEmpty($new_result))
                {
                    #If $new_result is blank or NULL
                    If ([string]::IsNullOrEmpty($old_result))
                    {
                        #If BOTH values are blank or NULL
                        WriteLog "[01]$user':' $new and $old both blank or NULL - Skipping";
                        #return;
                    }# end If
                    Else
                    {
                        #If only $new_result is blank or NULL
                        #WriteLog "[02]$user':' $new value is currently blank or NULL";
                        WriteLog "[02]$user':' Setting $new to value=$old_result";
                        Set-ADUser -Identity $user -Replace @{$new = $old_result};
                        [string]$new_result2 = Get-ADUser -Identity $user -Properties $new | Select -ExpandProperty $new;
                        #WriteLog "[02]$user':' $new value=$new_result2";

                        #Make sure value was updated
                        If ($new_result2 -eq $old_result)
                        {
                            #Clear the old attribute field
                            WriteLog "[03]$user':' Clearing $old value=$old_result";
                            Set-ADUser -Identity $user -Clear $old;
                            #[string]$old_result2 = Get-ADUser -Identity $user -Properties $old | Select -ExpandProperty $old;
                            #WriteLog "[03]$user':' $old value=$old_result2";
                            #return;
                        }# end If
                        Else
                        {
                            #Something unexpected happened
                            WriteLog "[04]$user':' $new value=$new_result2";
                            WriteLog "[04]$user':' $old value=$old_result";
                            WriteLog "[04]$user':' Whoa! Something went horribly wrong here - Skipping";
                            #return;
                        }# end Else
                    }# end Else
                }# end If
                Else
                {
                    #$new_result is NOT blank or NULL
                    If ([string]::IsNullOrEmpty($old_result))
                    {
                        #If only $old_result is blank or NULL
                        WriteLog "[05]$user':' $old blank or already cleared - Skipping";
                        #return;
                    }# end If
                    Else
                    {
                        #$new_result and $old_result BOTH NOT blank or NULL
                        If ($new_result -eq $old_result)
                        {
                            #Clear the old attribute field
                            WriteLog "[06]$user':' $new and $old values match...";
                            WriteLog "[06]$user':' Clearing $old value=$old_result";
                            Set-ADUser -Identity $user -Clear $old;
                            #[string]$old_result3 = Get-ADUser -Identity $user -Properties $old | Select -ExpandProperty $old;
                            #WriteLog "[06]$user':' New $old value=$old_result3";
                            #return;
                        }# end If
                        #$new_result and $old_result have data but don't match
                        Else
                        {
                            WriteLog "[07]$user':' $new value=$new_result";
                            WriteLog "[07]$user':' $old value=$old_result";
                            WriteLog "[07]$user':' $new and $old don't match!";
                            WriteLog "[07]$user':' Clearing $old value=$old_result";
                            Set-ADUser -Identity $user -Clear $old;
                            #[string]$old_result4 = Get-ADUser -Identity $user -Properties $old | Select -ExpandProperty $old;
                            #WriteLog "[07]$user':' New $old value=$old_result4";
                            #return;
                        }# end Else
                    }# end Else
                }# end Else
            }# end Try
            #If we get an error trying to read the attributes
            Catch
            {
                WriteLog "[08]$user':' $new value=$new_result";
                WriteLog "[08]$user':' $old value=$old_result";
                WriteLog "[08]$user':' Either or both of $new or $old don't exist - Skipping";
            }# end Catch
        }# end For
	}# end ForEach

}# end function main

Import-Module ActiveDirectory

Write-Output "Beginning processing $filename - please wait...";
Main;
Write-Output "Finished processing $filename. Please review $logfile for exceptions";
return;

I’m constantly amazed at the amount and high quality of examples on the interwebitudes that have helped me to this point. I know I’m late to the game, but I’m trying to get up to speed quickly, and currently devouring Don Jones’ two Lunches books. I know I have a ways to go to tighten up my coding style, etc, but I’m working on it.

Thanks all!

Script looks great! I would say if this script is supposed to run on all users accounts in an OU and not a specific list to gather your $users list from an AD query instead of a text file to make it more dynamic and less overhead to gather your list ahead of time.

Another great feature to add would be Write-Progress inside your foreach statement to give you a progress bar of which user your script is currently working on.