Automating ARS Scheduled Task Parameters

The blog title might seem a little confusing and I suspect that not many people are going to be searching for this.  

I thought it was a clever idea and I’ve been picking away at it for some time but I only completely solved it today.  As it turns out some of my earlier posts on how to write a function to get the ARS scheduled tasks had bugs in and I hadn’t even realised it.

I have quite a lot of ARS scheduled tasks in my environment.  I could write these to be monolithic with all the variables embedded but this means if I want to reuse the script for another scheduled task I can’t and if I want to change one of the variables at a later date I have to edit the script. So two problems,

1. the variables are not visible without reading the script and
2. I need to debug the script to change the variables.

Let’s quickly cover off how to get the scheduled task parameters. If you are running the script inside ARS, i.e. its actually the scheduled task running then you can use the intrinsic $Task.DirObject like this:

$Task.DirObj.GetInfo() 
$Task.DirObj.GetInfoEx(@('edsaParameters'),0)  
#  if no parameters are specified this command will trigger the catch clause
$strParameters         = $Task.DirObj.Get('edsaParameters')

if this is being run in an editor externally then you get the task parameters like this:

$Task = Get-QADObject -Identity $script:TaskDN  `
          -IncludedProperties edsaParameters,edsaModule -Proxy
$strParameters = $Task.edsaParameters

in both case you now need to convert the $strParameters variable to an [xml] object like this:

$strParameters = '<parameters>' + $strParameters + '</parameters>'
# and then return this variable using  
Return $strParameters
# and then convert to XML
$strParameters = Get-TaskParameters 
$xmlParameters = [xml]$strParameters

Now you can set your parameters to the scheduled task parameters like this

$emailTo       = [string]$xmlParameters.parameters.emailTo 

In my script function Get-TaskParameters I wrap these commands inside a try / catch clause. The script first tries to get the intrinsic object and falls back, using the catch clause to using the second method. As long as the $script:TaskDN is valid the function will successfully return the task parameters.

Some of my script use a lot of variables which I expose as ARS scheduled task parameters.  I always add defaults into the script so I can debug the script when writing it. I also set a flag so I know if any of the parameters were defaults rather than values taken from the scheduled task itself.  

$defaultUsed = $false # flag used to detect if all parameters were defaults
if ( ($emailTo -eq $null) -or ($emailTo.Length -le  1) ) { 
 $emailTo = "lee.andrews@myDomain.com" ; $defaultUsed = $true 
} 

In theory I don’t need to specify any parameters in the scheduled task unless I subsequently want to change the script behavior by using different task parameters. However I now have to remember which parameters I can add to the task to change it’s behavior, which in a years time may not be so obvious to me. That’s probably more like a few hours before I forget 😦  

A better way would be to copy each parameter from the script to the scheduled task but this is error prone and time consuming and as ‘scripters’ aren’t we all inherently lazy? OK maybe that’s not the best way of putting that, we like to speed things up with automation!

What if the script could update it’s own parameters on the first run or any run for that matter, how cool ( to us nerds ) would that be?

This idea had originally come to me because I had a task where one of the parameters was a group name and I thought, “what if someone changes the group name”.  I then thought “if I use the GUID of the group that couldn’t change!” Adding the group GUID as a parameter would be a nightmare so the solution was, in my mind at least, to get the script on each run to read the group name and then update the GUID in the task parameters if it needed to. I Thought I’d already posted this but it seems I can’t find it so I’ll add that as my next post.

Here is a modified version of my Get-TaskParameters function. If the scheduled task has no parameters then  
$strParameters = $Task.DirObj.Get(‘edsaParameters’) triggers the catch clause and then it uses the $script:taskDN variable to use the second method to get the parameters.

The $script:taskDN variable is used when debugging but it will fail if you reorganise your scheduled tasks. My ideal is for variable to only be required if we are debugging otherwise I want the task to dynamically figure out where it is using the intrinsic object. I’m writing more robust code if it can handle renames and container moves without modification.

If when my script runs it detects that some or all of the parameters were defaults, i.e. the task does not contain the parameter then my script creates a hash table of parameters and calls ‘Set-TaskParameters’.

Here’s all the code to do this including the new function Set-TaskParameters

function Get-TaskParameters {
 try {
  $Task.DirObj.GetInfo() 
  #  if no parameters are specified this will trigger the catch clause
  # we set the $Script:taskDNDefault dynamically in case we invoke catch
  $Script:taskDN         = $($Task.DirObj.Get('distinguishedName')) 
  $Task.DirObj.GetInfoEx(@('edsaParameters'),0)  
  $strParameters         = $Task.DirObj.Get('edsaParameters')
 }
 catch {
  try {
   $Task = Get-QADObject -Identity $script:TaskDN  `
                         -IncludedProperties edsaParameters,edsaModule `
                         -Proxy 
   $strParameters        = $Task.edsaParameters
  }
  catch {
   return 'Unable to get task parameters'
  }
 }
 $strParameters = '<parameters>' + $strParameters + '</parameters>' 
 return $strParameters
}

function Set-TaskParameters {
 param (
  $htParameters,
  $taskDN,
  $connection 
 )
 $htParameterList = @()
 foreach ( $htParameter in $htParameters.GetEnumerator() ) {
  $htParameterList += ` $('<'+$htParameter.key+'>'+$htParameter.value+'</'+$htParameter.key+'>')
 }
 Set-QADObject taskDN -ObjectAttributes @{edsaParameters=$htParameterList} `
                      -Connection $connection | Out-Null 
}

#here is example calling code 
$strParameters = Get-TaskParameters 
if ( $strParameters -eq 'Unable to get task parameters' ) {
 $subject = "$hostName $scriptName Script ERROR - Unable to get PARAMETERS"
 $emailParameters.Add('body',"$hostName  Line  $($error[0].InvocationInfo.ScriptLineNumber) - FATAL ERROR: Failed to get  script parameters")
 $emailParameters.Add('Subject',$subject)
 Send-MailMessage @emailParameters -Encoding ([System.Text.Encoding]::UTF8)
 throw $subject
}

$xmlParameters   = [xml]$strParameters
$emailTo         = [string]$xmlParameters.parameters.emailTo     
$emailFrom       = [string]$xmlParameters.parameters.emailFrom     
$operationReason = [string]$xmlParameters.parameters.operationReason
#Region Set Parameter Defaults
$defaultUsed = $false 
if ( ($emailTo -eq $null) -or ($emailTo.Length -le  1) ) { 
 $emailTo = "lee.andrews@MyDOmain.com" ; $defaultUsed = $true } 
if ( ($emailFrom -eq $null ) -or ($emailFrom.Length -le  1) ) { 
 $emailFrom = $scriptOwner ; $defaultUsed = $true } 
if ( ($operationReason -eq $null) -or ($operationReason.Length -le  1) ) {   $operationReason = $script:scriptName ; $defaultUsed = $true } 
# now check if we need to update the task parameters
if ( $defaultUsed ) {
 $taskParameters = @{
  'emailTo'         = $emailTo;
  'emailFrom'       = $emailFrom;
  'operationReason' = $operationReason;
 }
 Set-TaskParameters -htParameters $taskParameters `
                    -taskDN $script:taskDN `
                    -connection $proxy  
}

 
So your first run will automatically set all the parameters to the default values.

Is that neat or what? OK, OK I know I need to get out more 🙂
 

 

Advertisements

One thought on “Automating ARS Scheduled Task Parameters

  1. […] to my post on doing this ( https://clan8blog.wordpress.com/2017/03/16/automating-ars-scheduled-task-parameters/) I realised that I’d left out one little trick, or two in getting and updating the scheduled […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.