PowerShell: A Simple Batch Processing System, Part 1

batchHi.  I’ve written a few scripts that have gotten to be quite large.  In all cases they’ve needed to make a series of changes to a set of objects and log the results.  It’s normally important that some of the later changes only get made if the earlier ones are successful;  for example only changing the default SMTP address on a mailbox if another SMTP address was added earlier.

This series of posts will go into a decent system I’ve found for accomplishing this with some skeleton examples that are (hopefully!) easy to adapt.First, I’ll list the things that are normally important;

  • Process a list of objects from a CSV file.
  • Sanity check the data.
  • Make a series of consecutive changes to the objects. Sometimes changes are only attempted if a previous change is successful.
  • Optionally only run SOME of the changes if desired.
  • Log the results.

These can be applied to all sorts of sets of objects;  mailbox changes, AD updates, text updates to a file, server configuration etc.

The best way I’ve found for accomplishing all of these is to use a batch processing object that holds the status of every change you want to make to an item.  This processing object is passed between functions which actually make the changes;  as the changes complete the success (or failure) is added to the processing object that is then handed off to the next function in the chain.batchflow

At the end, you can use the set of processing objects to generate a report.  Additionally, you can dump the reporting objects to disk at various points so you get a ‘point in time’ save of what the script has done (in case the processing terminates early).

Functions we’re going to need;

  • Creating a Report Object.
  • Importing the CSV
  • Checking the CSV data is correct
  • Functions to make the changes we want
  • A controller to run the change functions and pass the report object between them
  • Output the results

The reporting object function needs to create a new report object that holds an identifier to the thing we’re going to update and the success of every operation we’re going to run on it.  Additionally maybe a note about any failures that occur.

function New-ReportObject
{
    Param
    (
        [Parameter(ValueFromPipeline=$true)]
        [PSObject]$TargetObject=$Null     
    )
    BEGIN
    {
    }
    PROCESS
    {
        $ReportObject=New-Object -typename PSObject 
        $ReportObject | Add-Member -MemberType NoteProperty -Name "Identifier" -Value ""
        $ReportObject | Add-Member -MemberType NoteProperty -Name "Task1Complete" -Value $False
        $ReportObject | Add-Member -MemberType NoteProperty -Name "Task2Complete" -Value $False
        $ReportObject | Add-Member -MemberType NoteProperty -Name "Note" -Value ""     
        if(!($TargetObject -eq $Null))
        {    
            $ReportObject.Identifier = $TargetObject.DistinguishedName
        }
        Return $ReportObject
    }
    END
    {
    }
}

This creates a new ReportObject with an Identifier field, two “Task Complete” boolean fields and a Note field.  If a TargetObject is passed it populates the Identifier with a unique representation of the object we’re going to make changes to.  Here I’ve assumed it’s going to be a mailbox so I’ve used the DistinguishedName but you could use anything (SamAccountName, UPN, a unique key etc).

The function accepts input from the pipeline.

More next time!

Leave a comment