My 2nd PoSH script: Remove-Attributes.ps1

This topic contains 1 reply, has 2 voices, and was last updated by Profile photo of Edmond Yee Edmond Yee 6 months, 2 weeks ago.

  • Author
    Posts
  • #39218
    Profile photo of Don Reese
    Don Reese
    Participant

    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!

  • #39264
    Profile photo of Edmond Yee
    Edmond Yee
    Participant

    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.

You must be logged in to reply to this topic.