This project is read-only.

powershell - monitor scheduled tasks

Topics: Developer Forum, User Forum
Jan 23, 2013 at 2:05 PM
Edited Jan 23, 2013 at 2:22 PM

Hello,

I am trying to have a powershell script fire off which looks for failed scheduled tasks and in the $Status.StatusText report what the task name was and the error code. It does not appear to be storing anything in the StatusText for some reason and I cannot figure out why. If i change the $Status.StatusText to a write-host and im in the powershell ISE it displays the information I am looking for correctly. I have tried a few different things such as casting the variable i'm passing the StatusText as a string but that did not appear to have made a difference. I either get nothing in the StatusText or I get a 0x0.

 

$schedule = new-object -com("Schedule.Service")
$schedule.connect("localhost")
$tasks = $schedule.getfolder("\").gettasks(0)
$StatusRaw = ''
$Status.StatusID=1
$Status.StatusText="All Clear"

$Completed = $tasks | ? {$_.LastTaskResult -eq 0}
$Failed = $tasks | ? {$_.LastTaskResult -ne 0}

foreach ($ta in $Failed)
{
$rcode = [Convert]::ToString($ta.LastTaskResult, 16).Insert(0,"0x")
if ($rcode -ne "0x0")
{$StatusRaw += ($ta.Name + ' Error Code: ' + $rcode + ' ')
}
}
$sStatus=[string]$StatusRaw
if ($Failed.Count -ne 0)
{$Status.StatusText=$sStatus
$Status.StatusID=3
}

looking at this some more it looks like it does post the name and error code, but it is not setting the StatusID to ok and always reports failed but with no statustext

Jan 23, 2013 at 5:04 PM

Well I got around what I was running into with this:

$schedule = new-object -com("Schedule.Service")
$schedule.connect("localhost")
$tasks = $schedule.getfolder("\").gettasks(0)
$StatusRaw = ''
$FailedFlag = ""
$Completed = $tasks | ? {$_.LastTaskResult -eq 0}
$Failed = $tasks | ? {$_.LastTaskResult -ne 0}

foreach ($ta in $Failed)
{
$rcode = [Convert]::ToString($ta.LastTaskResult, 16).Insert(0,"0x")
if ($rcode -ne "0x0")
{$StatusRaw += ($ta.Name + ' Error Code: ' + $rcode + ' || ')
$FailedFlag = "True"
}
}
$sStatus=[string]$StatusRaw

if ($FailedFlag -eq "True"){
$Status.StatusText=$sStatus
$Status.StatusID=[int]3
}
else{
$Status.StatusText="All Clear"
$Status.StatusID=[int]1
}

Feb 12, 2013 at 3:41 PM
Edited Feb 12, 2013 at 3:44 PM
I see you figured it out, glad to see it.

For my own purposes, in order to remove any vagaries of how the script result gets returned, I've begun using a function to display/return the data.
###########"Display Data" function#####################
function display_data{ 
if ($errlvl -gt 3){$errlvl = 3}     
    switch($errlvl){
        3   {if ($verbose -gt 0){$final_displaytext = "Monitor failure: "+($monitor_alarm_text| select -uniq)+" "+($monitor_info_text| select -uniq);break} 
                else {$final_displaytext = "Monitor failure: "+($monitor_alarm_text| select -uniq);break}}
        2   {if ($verbose -gt 0){$final_displaytext = "Monitor warning: "+($monitor_alarm_text| select -uniq)+" "+($monitor_info_text| select -uniq);break} 
                else {$final_displaytext = "Monitor warning: "+($monitor_alarm_text| select -uniq);break}}
        1   {if ($verbose -gt 0){$final_displaytext = "Monitor OK: "+($monitor_info_text);break}
                else {$final_displaytext = "Monitor OK";break}}
        default {$final_displaytext = "FAIL: Other script failure: "+($monitor_info_text| select -uniq);break}}
    $displaymessage = ("   "+$final_displaytext) -replace "   ,", ""
    Switch($polymon)
      {     1{$Status.StatusText=$displaymessage
              $Status.StatusID=$errlvl
              if (($counter.length) -gt 1)
                {$counter = $counter | select -uniq |sort-object
                 foreach ($count in $counter){$Counters.Add($count[0],$count[1])  }}}
            0{switch($errlvl){
                3{write-host  "Err LVL = FAIL: "$displaymessage}
                2{write-host  "Err LVL = WARN: "$displaymessage}
                1{write-host  "Err LVL = OK: "$displaymessage}}} }
    break}      
At the top of the script I choose whether I want "verbose" output or minimal, test whether we're running the inside Polymon or a raw Powershell window, and set the array variables I'll be populating as the script proceeds.

if($Counters){[DOUBLE]$polymon = 1;$Status.StatusText = ""} else {[DOUBLE]$polymon = 0}

[DOUBLE]$ERRLVL = 1
$monitor_info_text= @()
$monitor_alarm_text = @()
As the script proceeds, it increases the $ERRLVL if alarm conditions are found, and adds items to the $monitor_info_text and $monitor_alarm_text variables as needed.
(For my logic, $monitor_info_text is informational text that is always displayed with every script run. $monitor_alarm_text is error-specific text that's only displayed in case of an alarm condition)
$monitor_info_text+= ", "+$inst+":("+$Timestamp+")"

If ($Review_Integchck_Log -notlike '*No integrity errors were detected*') {[DOUBLE]$ERRLVL += 2 ; $monitor_alarm_text += ", "+$inst+": "+$Review_Integchck_Log}#;  display_data}
Once the $ERRLVL and $monitor_info_text and $monitor_alarm_text variables have been set, we simply execute the display_data function.

display_data
If the code is running in a raw powershell window, display_data writes the information to the display. If it's running inside Polymon, display_data populates the StatusID and StatusText variables that Polymon requires. As a result, I can do all my script/code building/debugging in a raw Powershell window, and then paste that code straight into a Polymon monitor without any changes to it.


See my post on "Parsing Unix log files" to see all this in context.