Public/system/Get-ScheduledTaskDetail.ps1
|
#Requires -Version 5.1 function Get-ScheduledTaskDetail { <# .SYNOPSIS Retrieves scheduled task details from local or remote computers .DESCRIPTION Queries the ScheduledTasks CIM namespace to enumerate scheduled tasks and their last/next run details. Returns typed PSWinOps.ScheduledTaskDetail objects with human-readable HRESULT translation. Microsoft built-in tasks are excluded by default to reduce noise. .PARAMETER ComputerName One or more computer names to query. Defaults to the local machine. Accepts pipeline input by value and by property name. .PARAMETER TaskPath Filter tasks by folder path. Defaults to all paths. Supports wildcards. Example: '\Backup\*' .PARAMETER TaskName Filter tasks by name using -like matching. Supports wildcards. Example: 'Backup*' .PARAMETER IncludeMicrosoftTasks Include tasks under the '\Microsoft\' path hierarchy. These are excluded by default as there are typically hundreds of built-in tasks. .PARAMETER Credential PSCredential object for remote authentication. Used when creating CimSessions to remote machines. .EXAMPLE Get-ScheduledTaskDetail Retrieves all non-Microsoft scheduled tasks from the local computer. .EXAMPLE Get-ScheduledTaskDetail -ComputerName 'SRV01' -TaskName 'Backup*' -Credential (Get-Credential) Retrieves scheduled tasks matching 'Backup*' on SRV01 with explicit credentials. .EXAMPLE 'SRV01', 'SRV02' | Get-ScheduledTaskDetail -TaskPath '\Maintenance\*' -IncludeMicrosoftTasks Queries multiple servers via pipeline for tasks in the Maintenance folder. .OUTPUTS PSWinOps.ScheduledTaskDetail Returns one object per scheduled task with ComputerName, TaskName, TaskPath, State, LastRunTime, LastTaskResult, LastResultMessage, NextRunTime, Author, Description, and Timestamp. .NOTES Author: Franck SALLET Version: 1.0.0 Last Modified: 2026-03-25 Requires: PowerShell 5.1+ / Windows only Requires: ScheduledTasks module (built-in on Windows 8+ / Server 2012+) .LINK https://github.com/k9fr4n/PSWinOps .LINK https://learn.microsoft.com/en-us/powershell/module/scheduledtasks/get-scheduledtask #> [CmdletBinding()] [OutputType('PSWinOps.ScheduledTaskDetail')] param( [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [Alias('CN', 'Name', 'DNSHostName')] [string[]]$ComputerName = $env:COMPUTERNAME, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$TaskPath, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$TaskName, [Parameter(Mandatory = $false)] [switch]$IncludeMicrosoftTasks, [Parameter(Mandatory = $false)] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Starting" $localNames = @($env:COMPUTERNAME, 'localhost', '.') } process { foreach ($machine in $ComputerName) { $cimSession = $null try { $isLocal = $localNames -contains $machine # --- Build or skip CimSession --- $taskParams = @{ ErrorAction = 'Stop' } if (-not $isLocal) { $sessionParams = @{ ComputerName = $machine ErrorAction = 'Stop' } if ($Credential -ne [System.Management.Automation.PSCredential]::Empty) { $sessionParams['Credential'] = $Credential } $cimSession = New-CimSession @sessionParams $taskParams['CimSession'] = $cimSession Write-Verbose -Message "[$($MyInvocation.MyCommand)] CimSession established to '$machine'" } # --- Retrieve all scheduled tasks --- Write-Verbose -Message "[$($MyInvocation.MyCommand)] Querying scheduled tasks on '$machine'" $allTasks = @(Get-ScheduledTask @taskParams) # --- Filter by TaskPath --- if ($PSBoundParameters.ContainsKey('TaskPath')) { $allTasks = @($allTasks | Where-Object -FilterScript { $_.TaskPath -like $TaskPath }) } # --- Exclude Microsoft tasks unless requested --- if (-not $IncludeMicrosoftTasks) { $allTasks = @($allTasks | Where-Object -FilterScript { $_.TaskPath -notlike '\Microsoft\*' }) } # --- Filter by TaskName if specified --- if ($PSBoundParameters.ContainsKey('TaskName')) { $allTasks = @($allTasks | Where-Object -FilterScript { $_.TaskName -like $TaskName }) } if ($allTasks.Count -eq 0) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] No matching tasks found on '$machine'" continue } Write-Verbose -Message "[$($MyInvocation.MyCommand)] Found $($allTasks.Count) task(s) on '$machine'" # --- Process each task --- foreach ($task in $allTasks) { $runInfo = $null try { $infoParams = @{ TaskName = $task.TaskName TaskPath = $task.TaskPath ErrorAction = 'SilentlyContinue' } if ($cimSession) { $infoParams['CimSession'] = $cimSession } # Module-qualified call to avoid recursion with our function name $runInfo = ScheduledTasks\Get-ScheduledTaskInfo @infoParams } catch { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Could not get run info for '$($task.TaskPath)$($task.TaskName)' on '$machine'" } $resultCode = if ($runInfo) { $runInfo.LastTaskResult } else { $null } $resultMessage = ConvertTo-ScheduledTaskResultMessage -ResultCode $resultCode [PSCustomObject]@{ PSTypeName = 'PSWinOps.ScheduledTaskDetail' ComputerName = if ($isLocal) { $env:COMPUTERNAME } else { $machine } TaskName = $task.TaskName TaskPath = $task.TaskPath State = $task.State.ToString() LastRunTime = if ($runInfo) { $runInfo.LastRunTime } else { $null } LastTaskResult = $resultCode LastResultMessage = $resultMessage NextRunTime = if ($runInfo) { $runInfo.NextRunTime } else { $null } Author = $task.Author Description = $task.Description Timestamp = Get-Date -Format 'o' } } } catch { Write-Error -Message "[$($MyInvocation.MyCommand)] Failed on '${machine}': $_" continue } finally { if ($cimSession) { Remove-CimSession -CimSession $cimSession -ErrorAction SilentlyContinue Write-Verbose -Message "[$($MyInvocation.MyCommand)] CimSession closed for '$machine'" } } } } end { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Completed" } } |