Checking your ARS Scheduled tasks ran OK

How do you know that all of your ARS scheduled tasks have completed successfully?

Well the only way provided by Quest is to look at the scheduled task information provided in the MMC.   You’ll notice there are three columns

  • name
  • Last Run Time
  • Last Run Message

Sadly the Last Run Message will generally be empty as it only displays errors so perhaps this should have been named Last Error Message!

The Last Run Time is useful but do you know when it was last supposed to run? To find that out you need to open the properties and read the schedule.

All of that aside though you have to remember to check!

For my ARS scheduled tasks I have always used the Last Run Message as a way of easily telling that the task ran without errors.

“All of my scheduled task scripts THROW an error on purpose!

This might seem a little odd but I force errors using “throw” so that I can write a message on the Last Run Message column.

This has worked well, but I still had to check that the script ran on schedule so I decided to write an audit script that will read the Last Run Messages, the last run time and understand the next run time and email me if it finds an unexpected error or that the script missed the last scheduled run time.

Getting the Last Run Message is simple, a task object has a property called ‘edsaLastActionMessage’ which contains the droid we are looking for.  ( A very sad reference to Star Wars – sorry couldn’t resist )

It would therefore be very easy to code an audit script to look for specific text to confirm the task had completed successfuly.

If I hard code the messages though I’ll need to update the audit script every time
I modify the scheduled task script or added a new scheduled task script.

I also didn’t want to be limited to specific text I could THROW in my scheduled task script so I decided to use a new parameter that I add to each scheduled task I want to audit, called LastRunLine.  This is dynamically updated by the script when it runs so is always correct even when I edit the script, i.e. I don’t need to remember to update it manually.

The first task is to get all of the scheduled tasks like this :

$taskParameterList = @(
 'name'
 'edsaDisableSchedule'
 'edsaXMLSchedule'
 'edsaLastRunTime'
 'edsvaNextRunTime'
 'edsaLastActionMessage'
 'edsaTaskState'
 'edsvaIsReadyToTerminate'
 'edsvaServerNameToExecute'
 'edsvaTaskStateString'
 'DN'
 'ParentContainerDN'
)
$tasksOU  = "CN=Clan8,CN=Scheduled Tasks,CN=Server Configuration,CN=Configuration" ' this is actually a parameter
$tasks     = Get-QADObject -SearchRoot $tasksOU -IncludedProperties $taskParameterList -Type edsScheduledTask | select $taskParameterList

We can then loop around the tasks we found like this : foreach ( $taskInfo in $tasks ) {

In each loop we can check if the task is currently running and it it is we have to ignore it as the last run message will be blank

if ( $taskInfo.edsvaTaskStateString -eq 'Task started its execution' ) {
Continue
}

We get the parameters of the task like this:

$strParameters = Get-ScheduledTaskParameters $taskInfo.DN
$lastRunTime = $taskInfo.edsaLastRunTime
$nextRunTime = $taskInfo.edsvaNextRunTime

I’m only interested in a task if I have a parameter called lastrunLine
if ( ! ( $lastRunLineNo = [string]$xmlParameters.parameters.lastRunLine ) ) {
Continue
}

Now we can check if we got a last run message and compare this with the expected string lastRunLineNo
Based on this outcome I can raise an alert or not.

An example last run message is: ‘At Line:425 Char:1 Found 60 users’ The first part of this string is automatically created by ARS.

I check the Line number the script ‘failed’ on with the LastRunLine parameter. If it matches then the task completed succesfully.

When getting the task details I also get the last run time and the next run time, ‘edsaLastRunTime’ and ‘edsvaNextRunTime’

This allows me to check if the task has missed it’s run time and raise an alert.

Lastly because I want my audit script to run every hour it would repeatedly report the same errors and ideally I only want this to be reported once.
To solve this issue I manually update the last run message prefixing it with ‘ERROR:’ using:

Set-QADObject $taskInfo.DN -ObjectAttributes @{edsalastactionmessage="ERROR: '$($taskInfo.edsaLastActionMessage.Trim())'"} -proxy

Here’s the full script. If you run this in an editor it will automatically set the debug parameters and display progress messages to screen as it goes.
This prevents you accidentily uploading the script to ARS with the debug parameter still set to true

#region Script Header : Audit-ScheduledTasks 
$script:scriptVersion = "2.00" 
$script:scriptName    = "Audit-ScheduledTasks_v$script:scriptVersion"
$script:Owner         = "lee.Andrews@mydomain.com" # used to send script specific error messages
$script:taskDN        = "CN=Audit-ScheduledTasks,CN=Audit,CN=Clan8,CN=Scheduled Tasks,CN=Server Configuration,CN=Configuration"
$thisLastRLNo         = 441 # update this line when you update the script
$errorInRun           = $true 
if ( $Task.DirObj ) {
 $script:ShowDebug = $false
}
else {
 $script:ShowDebug = $true
 cls 
 $padright = 100 
}
#endregion Script Header : Audit-ScheduledTasks
#region Set default SMTP variables
$emailParameters =@{
 "smtpServer"="smtp.,mydomain.com"
 "To"=$script:Owner
 "From"="NoReply@mydomain.com"
}
#endregion Set default SMTP variables
#region Version Control Information
<# 
  Version 1.00 Original
  Version 1.01 Automatically sets debug variable using the task object 
  Version 1.02 Adds Report Header and simplifies audit check 
  Version 1.03 Updated debug routines and auto update of the last run message if script is in Debug mode
  Version 2.00 Now uses the ARS 7.0 commandlets 
#>
#endregion Version Control Information
#region Helper functions
function Get-CurrentLineNumber {
 $MyInvocation.ScriptLineNumber
}
function Get-ModuleStatus { # http://www.ehloworld.com/938
	[CmdletBinding(SupportsShouldProcess=$true)]
	param (
		[parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="Enter the Module Name, e.g. Lync")]
		[string]$name
	)
	if(!(Get-Module -name "$name")) {
		if( Get-Module -ListAvailable | ? {$_.name -eq "$name"} ) {
			try { 
				Import-Module -Name "$name" 
				return $true
			}
			catch { return $false	}
		} 
		else { return $false }
	}
	else { return $true	}
} # end function Get-ModuleStatus
function Get-TaskParameters {
 function Convert-OctetStringToGuid {
  param (
   [Parameter(Mandatory=$True,Position=1)][string]$Guid
  )
  if(32 -eq $guid.Length) {
   [UInt32]$a = [Convert]::ToUInt32(($guid.Substring(6, 2) + $guid.Substring(4, 2) + $guid.Substring(2, 2) + $guid.Substring(0, 2)), 16)
   [UInt16]$b = [Convert]::ToUInt16(($guid.Substring(10, 2) + $guid.Substring(8, 2)), 16)
   [UInt16]$c = [Convert]::ToUInt16(($guid.Substring(14, 2) + $guid.Substring(12, 2)), 16)

   [byte]$d = ([Convert]::ToUInt16($guid.Substring(16, 2), 16) -as [byte])
   [byte]$e = ([Convert]::ToUInt16($guid.Substring(18, 2), 16) -as [byte])
   [byte]$f = ([Convert]::ToUInt16($guid.Substring(20, 2), 16) -as [byte])
   [byte]$g = ([Convert]::ToUInt16($guid.Substring(22, 2), 16) -as [byte])
   [byte]$h = ([Convert]::ToUInt16($guid.Substring(24, 2), 16) -as [byte])
   [byte]$i = ([Convert]::ToUInt16($guid.Substring(26, 2), 16) -as [byte])
   [byte]$j = ([Convert]::ToUInt16($guid.Substring(28, 2), 16) -as [byte])
   [byte]$k = ([Convert]::ToUInt16($guid.Substring(30, 2), 16) -as [byte])

   [Guid]$g = New-Object Guid($a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k)
   return $g.Guid;
  }
  else {
   throw Exception("Input string is not a valid octet string GUID")
  }
 } # end function Convert-OctetStringToGuid 
 try {
  $Task.DirObj.GetInfo() 
  $Script:taskDN         = $($Task.DirObj.Get('distinguishedName')) # set to the actual task DN in case we trigger the catch clause
  $Task.DirObj.GetInfoEx(@('edsaParameters'),0)  #  if no parameters are specified this command will trigger the catch clause
  $strParameters         = $Task.DirObj.Get('edsaParameters')
  $Script:taskDNDefault  = "Scheduled Task...: $($Task.DirObj.Get('distinguishedName')). `r`n"  
  $byteString            = $Task.DirObj.Get('edsaModule')
  $byteString            = [BitConverter]::ToString($byteString)
  $OctetString           = $byteString.replace('-','')
  $taskModule            = Convert-OctetStringToGuid -Guid $OctetString 
  $script:scriptName     = $(Get-QADObject $taskModule -proxy  ).name 
 }
 catch {
  try {
   $Task                 = Get-QADObject -Identity $script:TaskDN  -proxy  -IncludedProperties edsaParameters,edsaModule 
   $strParameters        = $Task.edsaParameters
   $Script:taskDNDefault = "Scheduled Task...: $script:taskDN`r`n"  
   $taskModule           = Convert-OctetStringToGuid $Task.edsaModule 
   $script:scriptName    = $(Get-QADObject $taskModule -proxy  ).name 
  }
  catch {
   return 'Unable to get task parameters'
  }
 }
 $strParameters = '<parameters>' + $strParameters + '</parameters>' 
 if ( Test-Path variable:Task        ) { Remove-Variable -Name Task        -ErrorAction SilentlyContinue }
 if ( Test-Path variable:byteString  ) { Remove-Variable -Name byteString  -ErrorAction SilentlyContinue }
 if ( Test-Path variable:OctetString ) { Remove-Variable -Name OctetString -ErrorAction SilentlyContinue }
 return $strParameters
}
function Set-TaskParameters {
 param (
  [Parameter(Mandatory=$True,Position=1)]$htParameters,
  [Parameter(Mandatory=$True,Position=2)]$taskDN,
  [Parameter(Mandatory=$True,Position=3)]$connection 
 )
 $htParameterList = @()
 foreach ( $htParameter in $htParameters.GetEnumerator() ) {
  $htParameterList += $('<'+$htParameter.key+'>'+$htParameter.value+'</'+$htParameter.key+'>')
 }
 $null = Set-QADObject $taskDN -ObjectAttributes @{edsaParameters=$htParameterList} -proxy 
}
function Stop-ScriptRun {
 param (
  [Parameter(Mandatory=$True ,Position=1)][hashtable]$emailParameters,
  [Parameter(Mandatory=$True ,Position=2)][string]$throwMessage, 
  [Parameter(Position=3)][allowNull()][string]$logfile,
  [switch]$sendMail,
  [switch]$stop 
 )
 $emailBody = $emailParameters.item("body").split("`r`n")
 if ( ( $logfile ) -and ( Test-Path $logfile ) ) {
  foreach ( $line in $emailBody ) {
   $line | Out-File -FilePath $logfile -Append 
  }
 }
 try {
  if ($sendMail) {
   Send-MailMessage @emailParameters -Encoding ([Text.Encoding]::UTF8)
  }
  $returnMessage = "$throwMessage" + " " + $emailParameters.Item("Subject") + " :"
 }
 catch { $returnMessage += "$throwMessage UNABLE TO SEND EMAIL - $($emailParameters.Item('Subject')) :" }
 if ( $stop ) { 
  throw $returnMessage 
 }
 return $returnMessage
}
function Get-ScheduledTaskParameters {
 param ( $taskDN ) 
 try {
  $Task                 = Get-QADObject -Identity $taskDN  -proxy  -IncludedProperties edsaParameters,edsaModule 
 }
 catch {
  return 'Unable to get task parameters'
 }
 $strParameters        = $Task.edsaParameters
 $strParameters = '<parameters>' + $strParameters + '</parameters>' 
 if ( Test-Path variable:Task        ) { Remove-Variable -Name Task        -ErrorAction SilentlyContinue }
 return $strParameters
}
#endregion Helper functions
#region Connect to ARS service
if ( ( Get-ModuleStatus "ActiveRolesManagementShell" ) -eq $false ) { # load the quest cmdlets
 $message = "ActiveRolesManagementShell could not be loaded SCRIPT HALTING - Please investigate"
 $emailParameters.Add("body",$message)
 $emailParameters.Add("Subject","$scriptName Script FATAL ERROR - Unable to Load ARS COMMANDLETS")
 Stop-ScriptRun $emailParameters -stop -throwMessage "FATAL ERROR - Unable to Load ARS COMMANDLETS" -sendMail
} # throw if we are unable to load the Quest cmdlets
$script:hostname = $env:COMPUTERNAME
$script:hostCode = "$($script:hostName.substring(0,1))$($script:hostName.substring($($script:hostName.length-2),2))"
try { $proxy = Connect-QADService -Proxy -Service "PLONWBQSTS20.Clan8.ad.Clan8.com"  }
catch { 
 $subject = "FATAL ERROR: $script:hostname '$script:scriptName' Line No. $($error[0].InvocationInfo.ScriptLineNumber) - Unable to Connect to ARS server"
 $emailParameters.Add('body',"************* $script:hostname : Line $($error[0].InvocationInfo.ScriptLineNumber) - FATAL ERROR Unable to Connect to ARS server ******************" )
 $emailParameters.Add('Subject',$subject)
 Send-MailMessage @emailParameters -Encoding ([Text.Encoding]::UTF8)
 throw $subject
}
#endregion Connect to ARS service
#region Get Task Parameters
$strParameters      = Get-TaskParameters # returns an XML object containing all of the scheduled task parameters
if ( $strParameters -eq "Unable to get task parameters" ) {
 $emailParameters.Add("body","************* Line $($error[0].InvocationInfo.ScriptLineNumber) - FATAL ERROR: Failed to get script parameters ******************")
 $emailParameters.Add("Subject","$scriptName Script FATAL ERROR - Unable to get TASK PARAMETERS")
 Stop-ScriptRun $emailParameters -stop -throwMessage "FATAL ERROR - Unable to get TASK PARAMETERS" -sendMail 
}
$xmlParameters = [xml]$strParameters     
$emailAlert    = [string]$xmlParameters.parameters.emailAlert
$emailFrom     = [string]$xmlParameters.parameters.emailFrom 
$latestRunDate = [string]$xmlParameters.parameters.latestRunDate
$tasksOU       = [string]$xmlParameters.parameters.tasksOU
$smtpServer 	  = [string]$xmlParameters.parameters.smtpServer
$lastRunLine   = [string]$xmlParameters.parameters.lastRunLine
#endregion Get Task Parameters
#region set defaults if any paramters are missing
$defaultUsed = $false 
if ( $emailAlert  -eq '' ) { $defaultUsed = $true ; $emailAlert  = $script:Owner } else { $emailAlert = $emailAlert.split(",") }
if ( $emailFrom   -eq '' ) { $defaultUsed = $true ; $emailFrom   = $script:Owner } 
if ( $latestRunDate -eq '' ) { $defaultUsed = $true ; $latestRunDate = (Get-Date -Hour 0 -Minute 00 -Second 00).addDays(-1) } else { $latestRunDate = $(Get-Date $latestRunDate -Format "dd/MM/yyyy HH:mm:ss") }
if ( $lastRunLine -eq '' ) { $defaultUsed = $true ; $lastRunLine = $thisLastRLNo } 
if ( $tasksOU     -eq '' ) { $defaultUsed = $true ; $tasksOU     = "CN=Clan8,CN=Scheduled Tasks,CN=Server Configuration,CN=Configuration" } 
if ( $smtpserver  -eq '' ) { $defaultUsed = $true ; $smtpserver  = "smtp.Clan8.com" }
if ( [string]$xmlParameters.parameters.scriptOwner -eq "" ) {
 $defaultUsed = $true 
}
else {
 if ( $script:Owner -ne [string]$xmlParameters.parameters.scriptOwner ) {
  $script:Owner = [string]$xmlParameters.parameters.scriptOwner
 }
}
#endregion set defaults if any paramters are missing
#region Upload any missing default parameters to the calling scheduled task
if ( $defaultUsed ) {
 $taskParameters = @{
  'emailAlert'  = $($emailAlert -join ",")
  'emailFrom'   = $emailFrom
  'lastRunLine' = $lastRunLine
  'latestRunDate' = $(Get-Date $latestRunDate -Format "dd/MM/yyyy HH:mm:ss")
  'ScriptOwner' = $script:Owner 
  'smtpserver'  = $smtpserver
  'tasksOU'     = $tasksOU 
 }
 $Error.Clear()
 Set-TaskParameters -htParameters $taskParameters -taskDN $script:taskDN -connection $proxy
 $emailParameters.Add("body","Missing Parameter - Scheduled Task Updated and script halted.  Please run again after checking the parameters are set correctly")
 $emailParameters.Add("Subject","$scriptName Script Missing Parameter")
 Stop-ScriptRun $emailParameters -stop -throwMessage "Missing Parameter - Please run again after checking the parameters are set correctly" -sendMail
}
#endregion Upload any missing default parameters to the calling scheduled task
#region Set Script Runtime Parameters
$taskParameterList = @(
 'name'
 'edsaDisableSchedule'
 'edsaXMLSchedule'
 'edsaLastRunTime'
 'edsvaNextRunTime'
 'edsaLastActionMessage'
 'edsaTaskState'
 'edsvaIsReadyToTerminate'          
 'edsvaServerNameToExecute'
 'edsvaTaskStateString'
 'DN'
 'ParentContainerDN'
)
$tasks  = Get-QADObject -SearchRoot $tasksOU -IncludedProperties $taskParameterList -Type edsScheduledTask | select $taskParameterList
$report = ""
$fullReport = ""
$updateRunDate = $false 
if ( $script:showDebug ) {	Write-Host "".padright($padright,"=") -ForegroundColor Green -BackgroundColor Black }
$fullReport  = "================================================================================================================= `n"
$fullReport += "Script Name.......: '$script:scriptName' `n"
$fullReport += "Script Version....: '$script:scriptVersion' `n"
$fullReport += "Host Server.......: '$($env:COMPUTERNAME)' `n" 
$fullReport += "================================================================================================================= `n"
foreach ( $taskInfo in $tasks ) {
 if ( $taskInfo.Name -eq "Update-ManagedDomains" ) {
  $bp = 0 
 }
 if ( $taskInfo.edsvaTaskStateString -eq 'Task started its execution' ) { 
  $skippingMsg = "Skipping task $($taskInfo.name) as it is currently running"
  $fullReport += "$skippingMsg `n"
  $fullReport += "----------------------------------------------------------------------------------------------------------------- `n"
  if ( $script:showDebug ) {
   Write-Host "$skippingMsg".padright($padright) -ForegroundColor Gray -BackgroundColor Black 
   Write-Host "".padright($padright,"-") -ForegroundColor Green -BackgroundColor Black 
  } # if ( $script:showDebug ) {
  continue 
 } # if ( $taskInfo.edsvaTaskStateString -eq 'Task started its execution' ) {
 #Region Reset loop variables 
 $loopReport = ""
 $NumberStart = $null
 $NumberEnd   = $null 
 $errorInLoop = $false 
 #EndRegion Reset loop variables 
 if ( $taskInfo.edsaDisableSchedule ) { 
  $skippingMsg = "Skipping $($taskInfo.name) as it's disabled" 
  $fullReport += "$skippingMsg `n"
  $fullReport += "----------------------------------------------------------------------------------------------------------------- `n"
  if ( $script:showDebug ) {	
   Write-Host "$skippingMsg".padright($padright) -ForegroundColor Gray -BackgroundColor Black 
   Write-Host "".padright($padright,"-") -ForegroundColor Green -BackgroundColor Black 
  }
  continue 
 }  
 #Region  Set task variables
 $xmlData           = [xml]$taskInfo.edsaXMLSchedule
 $lastRunTime       = $taskInfo.edsaLastRunTime 
 $nextRunTime       = $taskInfo.edsvaNextRunTime 
 #if ( ( Get-Date (Get-Date) -Format d ) -eq (get-date $nextRunTime -Format d ) ) {
 $strParameters     = Get-ScheduledTaskParameters $taskInfo.DN  # returns an XML object containing all of the scheduled task parameters
 $xmlParameters     = [xml]$strParameters     
 if ( ! ( $lastRunLineNo     = [string]$xmlParameters.parameters.lastRunLine ) ) { 
  $skippingMsg = "Skipping task $($taskInfo.name) as it does not have the lastRunNo parameter so is out of scope"
  $fullReport += "$skippingMsg `n"
  $fullReport += "----------------------------------------------------------------------------------------------------------------- `n"
  if ( $script:showDebug ) {	
   Write-Host "$skippingMsg".padright($padright) -ForegroundColor Gray -BackgroundColor Black 
   Write-Host "".padright($padright,"-") -ForegroundColor Green -BackgroundColor Black 
  }
  continue 
 }
 $taskInfoNameMsg  = "Task Name.........: '$($taskInfo.Name)'"
 $taskContainerMsg = "Task Folder.......: '$($taskInfo.ParentContainerDN.Replace("",$tasksOU"",'').substring(3))'"
 $taskServerMsg    = "Task Server.......: '$($taskInfo.edsvaServerNameToExecute)'"
 if ( $script:showDebug ) {	Write-Host "$taskInfoNameMsg".padright($padright)  -ForegroundColor Green -BackgroundColor Black }
 if ( $script:showDebug ) {	Write-Host "$taskContainerMsg".padright($padright) -ForegroundColor Green -BackgroundColor Black }
 if ( $script:showDebug ) {	Write-Host "$taskServerMsg".padright($padright)    -ForegroundColor Green -BackgroundColor Black }
 $loopReport += "$taskInfoNameMsg `n"
 $loopReport += "$taskContainerMsg`n"
 $loopReport += "$taskServerMsg`n"
 try { $lastActionMessage = "'$($taskInfo.edsaLastActionMessage.Trim())'" } 
 catch { 
  $bp = 0 
 }
 #EndRegion  Set task variables
 #Region Get LastRunLineNo Position  
 if ( $lastActionMessage.length -gt 0  ) { 
  if ( ( $lastActionMessage.IndexOf("ERROR") -ge 0 ) -and ( $taskInfo.DN -ne $script:taskDN ) ) {
   $taskErrorMsg = "Task ERROR already reported so skipping"
   if ( $script:showDebug ) {	Write-Host "$taskErrorMsg".padright($padright) -ForegroundColor Yellow -BackgroundColor Black }
   if ( $script:showDebug ) {	Write-Host "".padright($padright,"-")          -ForegroundColor Green  -BackgroundColor Black }
   $fullReport += $loopReport
   $fullReport += $taskErrorMsg
   $fullReport += "----------------------------------------------------------------------------------------------------------------- `n"
   continue
  }
  $lastRunMessage = "Last Run Message..: $lastActionMessage"
  if ( $script:showDebug ) {	Write-Host "$lastRunMessage".padright($padright) -ForegroundColor Green -BackgroundColor Black }
  $loopReport += "$lastRunMessage `n"
  $NumberStart = $lastActionMessage.IndexOf(":")+2
  $NumberEnd   = $lastActionMessage.IndexOf("char:")-$($NumberStart+1)
  try   { $derivedLineMsg = "Derived last line.: '$($lastActionMessage.Substring($NumberStart,$NumberEnd))'" }
  catch { $derivedLineMsg = "Derived last line.: None" }
  if ( $script:showDebug ) {	Write-Host "$derivedLineMsg".padright($padright) -ForegroundColor Green -BackgroundColor Black }
  $loopReport += "$derivedLineMsg `n" 
 } # if ( $lastActionMessage.length -gt 0  ) {
 else {
  $lastRunMessage = "Last Run Message..: 'ERROR: no last run message'"
  if ( $script:showDebug ) {	Write-Host "$lastRunMessage".padright($padright) -ForegroundColor Green -BackgroundColor Black }
  $loopReport += "$lastRunMessage `n"
 } # else if ( $lastActionMessage.length -gt 0  ) {
 $lastRunLineNoMsg = "LastRunLine was...: '$lastRunLineNo'"
 if ( $script:showDebug ) {	Write-Host "$lastRunLineNoMsg".padright($padright) -ForegroundColor Green -BackgroundColor Black }
 $loopReport += "$lastRunLineNoMsg `n"
 #EndRegion Get LastRunLineNo Position  
 #Region Check if task ran as expected
 if ( $xmlData.Schedule.Daily ) { 
  if ( $xmlData.Schedule.Daily.every ) {
   $unit = $xmlData.Schedule.Daily.every
   $units = "'Every $unit day(s) @ $time'" 
  }
  if ( $xmlData.Schedule.Daily.Start ) {
   if ( $xmlData.Schedule.Daily.Start.time ) {
    $time = Get-Date ([datetime]($xmlData.Schedule.Daily.Start.time)) -f T  
   } # if ( $xmlData.Schedule.Daily.Start.time ) {
  } # if ( $xmlData.Schedule.Daily.Start ) {
 } # if ( $xmlData.Schedule.Daily ) { 
 elseif ( $xmlData.Schedule.Monthly ) { 
  $DayOfWeek = $xmlData.Schedule.Monthly.days.weekday.'#text'
  $which = $xmlData.Schedule.Monthly.days.weekday.which
  $units = "'The $which $DayOfWeek of each Month'"
 }
 $scheduledUnitsMsg = "Schedule..........: $units "
 if ( $script:showDebug ) {	Write-Host "$scheduledUnitsMsg".padright($padright) -ForegroundColor Green -BackgroundColor Black }
 $loopReport += "$scheduledUnitsMsg `n"  
 try   { $lastRunMsg = "Last Run..........: '$(get-date $lastRunTime -Format 'ddd, MMM dd, yyyy @ HH:mm' )'" }
 catch { $lastRunMsg = "Last Run..........: Not Available" }
 $loopReport += "$lastRunMsg `n"   
 if ( $script:showDebug ) {	Write-Host "$lastRunMsg".padright($padright) -ForegroundColor Green -BackgroundColor Black }
 try   { $nextRunMsg = "Next Run..........: '$(get-date $nextRunTime -Format 'ddd, MMM dd, yyyy @ HH:mm')'" }
 catch {$nextRunMsg = "Next Run..........: Not Available" }
 if ( $script:showDebug ) {	Write-Host "$nextRunMsg".padright($padright) -ForegroundColor Green -BackgroundColor Black }
 $loopReport += "$nextRunMsg `n"  
 #EndRegion Check if task ran as expected
 if ( ( (Get-Date) -lt $nextRunTime ) -and ( ( $taskInfo.DN -eq $script:taskDN  ) -or ( ( $lastActionMessage.Length -gt 0  ) -and ( $lastRunLineNo -eq $($lastActionMessage.Substring($NumberStart,$NumberEnd)) ) ) ) ) {
  if ( $script:showDebug ) {	Write-Host "Last Run..........: 'Succesfull'".padright($padright) -ForegroundColor Cyan -BackgroundColor Black }
  $loopReport += "Last Run..........: 'Succesfull' `n"
 } # if ( ( (get-date) -lt $nextRunTime ) -and ( ( $taskInfo.DN -eq $script:taskDN  ) -or ( ( $lastActionMessage.Length -gt 0  ) -and ( $lastRunLineNo -eq $($lastActionMessage.Substring($NumberStart,$NumberEnd)) ) ) ) ) {
 else {
  $errorInLoop = $true
  if ( (Get-Date) -gt $nextRunTime ) {
   try { Set-QADObject $taskInfo.DN -ObjectAttributes @{edsalastactionmessage="ERROR: Missed last runtime"} -proxy }
   catch {
    $bp = 0 
   }
  }
  elseif ( $lastActionMessage.Length -gt 0 ) {
   try { Set-QADObject $taskInfo.DN -ObjectAttributes @{edsalastactionmessage="ERROR: '$($taskInfo.edsaLastActionMessage.Trim())'"} -proxy }
   catch {
    $bp = 0 
   }
  } # if ( $lastActionMessage.Length -gt 0 ) {
  else {
   Set-QADObject $taskInfo.DN -ObjectAttributes @{edsalastactionmessage="ERROR: task does not appear to have run please check any relevant logs"} -proxy 
   if ( $script:showDebug ) {	Write-Host "ERROR: task does not appear to have run please check any relevant logs".padright($padright) -ForegroundColor Yellow -BackgroundColor Black }
   $loopReport += "ERROR: task does not appear to have run please check any relevant logs `n"
  }
 } # else if ( ( (get-date) -lt $nextRunTime ) -and ( ( $taskInfo.DN -eq $script:taskDN  ) -or ( ( $lastActionMessage.Length -gt 0  ) -and ( $lastRunLineNo -eq $($lastActionMessage.Substring($NumberStart,$NumberEnd)) ) ) ) ) {
 $loopReport += "----------------------------------------------------------------------------------------------------------------- `n"
 if ( $errorInLoop )  {
  $report += $loopReport
 }
 $fullReport += $loopReport 
 if ( $script:showDebug ) {	Write-Host "".padright($padright,"-") -ForegroundColor Green -BackgroundColor Black  } 
} # ForEach ( $taskInfo in $tasks ) {
if ( $report.Length -gt 0 ) {
 if ( $script:showDebug ) {	Write-Host "".padright($padright,"=") -ForegroundColor Green -BackgroundColor Black }
 $report = "=============================================================================================================================== `n" + $report  
 # send an error report 
 Send-MailMessage -To $emailAlert -From $emailFrom -Body $report -SmtpServer $smtpServer -Subject "ERROR in ARS Scheduled Task Please investigate - $env:COMPUTERNAME" 
}
else {
 $errorInRun = $false 
}
$thisLastRLNo =  (Get-CurrentLineNumber) + 25
if ( $script:showDebug ) {	 Write-Host  "Line No = $thisLastRLNo".padright($padright) -ForegroundColor  Yellow -BackgroundColor Black } 
if ( $thisLastRLNo -ne $lastRunLine ) {
 $taskParameters = @{
  'emailAlert'  = $($emailAlert -join ",")
  'emailFrom'   = $emailFrom
  'lastRunLine' = $thisLastRLNo  
  'latestRunDate' = $(Get-Date $latestRunDate -Format "dd/MM/yyyy HH:mm:ss")
  'ScriptOwner' = $script:Owner 
  'smtpserver'  = $smtpserver
  'tasksOU'     = $tasksOU 
 }
 $Error.Clear()
 Set-TaskParameters -htParameters $taskParameters -taskDN $script:taskDN -connection $proxy
}
if ( $errorInRun -eq $false ) {
 $throwMessage = "Completed succesfully - $env:COMPUTERNAME"  
}
else {
 $throwMessage = "One or more tasks failed to complete please investigate - $env:COMPUTERNAME"
}
if ( $script:ShowDebug ) {
 $msg = "At line: $thisLastRLNo char:1. $throwMessage"
 Set-QADObject $script:TaskDN  -ObjectAttributes @{edsalastactionmessage=$msg} -proxy | Out-Null 
}
throw $throwMessage

 

Advertisements

2 thoughts on “Checking your ARS Scheduled tasks ran OK

  1. do you have any info on adding an operation reason to a change (i.e, change uses password) that doens’t require an approval task?

    • Hi if you mean can you update the Change History post change, then no, as this is stored in the history database and would need direct access to the SQL tables.

      You can add a comment to the change history only when making a change using the -control parameter which is available on the set-qad commands -control @(operationReason=”Your Text here”} I use this on most if not all of my published scripts here as this is best practice, especially when changes are made using automated tasks.

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.