PowerShell Script to Export Task Scheduler Details: Name, Status, Triggers, NextRunTime & More


13 views

When working with Windows Task Scheduler programmatically, the Schedule.Service COM object provides comprehensive access. Here's how to properly retrieve all required fields including those that initially appear empty:

$schedule = New-Object -ComObject("Schedule.Service") 
$schedule.Connect() 
$tasks = $schedule.GetFolder("\").GetTasks(0)

The key issue in your script is that some properties need special handling. Here's the corrected approach:

$taskDetails = foreach ($task in $tasks) {
    [PSCustomObject]@{
        Name = $task.Name
        Status = $task.State
        Triggers = ($task.Definition.Triggers | Out-String).Trim()
        NextRunTime = $task.NextRunTime
        LastRunTime = $task.LastRunTime
        LastRunResult = "0x{0:X8}" -f $task.LastTaskResult
        Author = $task.Definition.RegistrationInfo.Author
        Created = $task.Definition.RegistrationInfo.Date
        Actions = ($task.Definition.Actions | Select-Object -ExpandProperty Path) -join "n"
    }
}

$taskDetails | Format-Table -AutoSize

Some properties require special conversion:

# For better trigger visualization:
function Get-TriggerDetails {
    param($trigger)
    switch ($trigger.Type) {
        1 { "Daily" }
        2 { "Weekly" }
        3 { "Monthly" }
        4 { "MonthlyDay" }
        5 { "OnIdle" }
        6 { "AtStartup" }
        7 { "AtLogon" }
        8 { "EventTrigger" }
        9 { "RegistrationTrigger" }
        10 { "SessionStateChangeTrigger" }
    }
}

# Enhanced output:
$tasks | ForEach-Object {
    $triggerInfo = $_.Definition.Triggers | ForEach-Object {
        "{0} (Start: {1})" -f (Get-TriggerDetails $_), $_.StartBoundary
    }
    
    [PSCustomObject]@{
        Name = $_.Name
        Status = switch ($_.State) {
            0 { "Unknown" }
            1 { "Disabled" }
            2 { "Queued" }
            3 { "Ready" }
            4 { "Running" }
        }
        Triggers = $triggerInfo -join "n"
        NextRunTime = if ($_.NextRunTime) { $_.NextRunTime } else { "Not scheduled" }
        LastRunTime = if ($_.LastRunTime) { $_.LastRunTime } else { "Never run" }
        LastRunResult = "0x{0:X8}" -f $_.LastTaskResult
        Author = $_.Definition.RegistrationInfo.Author
        Created = $_.Definition.RegistrationInfo.Date
    }
}

For better sharing and analysis:

$taskDetails | Export-Csv -Path "TaskSchedulerReport.csv" -NoTypeInformation -Encoding UTF8

To focus on particular tasks:

$filteredTasks = $tasks | Where-Object {
    $_.Name -like "*Backup*" -or 
    $_.Definition.RegistrationInfo.Author -like "*Admin*"
}

When working with Windows Task Scheduler via PowerShell, many developers struggle to retrieve complete task information. The default COM object approach often leaves out crucial fields like Status, Triggers, and LastRunResult. Here's how to properly extract all relevant task details.

This enhanced script provides full access to all Task Scheduler properties by properly accessing the underlying XML definition of each task:

# Connect to Task Scheduler service
$schedule = New-Object -ComObject("Schedule.Service")
$schedule.Connect()
$rootFolder = $schedule.GetFolder("\")
$tasks = $rootFolder.GetTasks(0)

# Create custom object collection
$taskDetails = @()

foreach ($task in $tasks) {
    $xml = [xml]$task.Xml
    $taskObj = [PSCustomObject]@{
        Name = $task.Name
        Status = $task.State
        Triggers = ($xml.Task.Triggers | Out-String).Trim()
        NextRunTime = $task.NextRunTime
        LastRunTime = $task.LastRunTime
        LastRunResult = "0x{0:X}" -f $task.LastTaskResult
        Author = $xml.Task.RegistrationInfo.Author
        Created = $xml.Task.RegistrationInfo.Date
    }
    $taskDetails += $taskObj
}

# Output results
$taskDetails | Format-Table -AutoSize

The script now properly handles several problematic areas:

  • Status: Uses the .State property instead of .Status
  • Triggers: Extracts complete trigger information from the XML definition
  • LastRunResult: Formats the result code in hexadecimal format (like Task Scheduler UI)
  • Author/Created: Pulls from RegistrationInfo in the XML definition

For better reporting and analysis, you can export the results to CSV:

$taskDetails | Export-Csv -Path "TaskSchedulerReport.csv" -NoTypeInformation -Encoding UTF8

Some tasks may have complex trigger configurations. This enhanced version provides better trigger details:

function Get-TriggerDetails {
    param([xml]$taskXml)
    
    $triggers = @()
    foreach ($trigger in $taskXml.Task.Triggers.ChildNodes) {
        $triggerDetail = @{
            Type = $trigger.LocalName
            Enabled = $trigger.Enabled
        }
        
        # Add type-specific details
        switch ($trigger.LocalName) {
            "CalendarTrigger" {
                $triggerDetail.Add("StartBoundary", $trigger.StartBoundary)
                $triggerDetail.Add("ExecutionTimeLimit", $trigger.ExecutionTimeLimit)
            }
            "LogonTrigger" { 
                $triggerDetail.Add("UserId", $trigger.UserId) 
            }
        }
        $triggers += $triggerDetail
    }
    return ($triggers | ConvertTo-Json -Depth 3)
}

# Usage in main script:
$triggerDetails = Get-TriggerDetails -taskXml $xml