如何用PowerShell提取任务计划事件时间并计算执行时长
问题:获取Windows任务计划程序中任务的执行时长
我并非开发人员,出于运维需求需要编写PowerShell脚本获取Windows任务计划程序中任务的执行时长。我的思路是在事件查看器中筛选目标任务,提取ID为100(启动事件)和102(完成事件)的两个事件,计算二者的时间差。我已经通过
Get-WinEvent -FilterHashtable $filter成功获取到这两个事件,但不知道如何从事件中提取实际的启动和完成时间(当前脚本中$StartTime和$EndTime是过滤时间范围,并非事件的实际时间,导致计算出的$timeDifference错误)。请问如何提取事件的时间并计算二者的时间差?
原脚本:
#Variables $TaskName = '\TestTask' $StartTime = (Get-Date).AddDays(-1) $EndTime = Get-Date $filter = @{ LogName = 'Microsoft-Windows-TaskScheduler/Operational' ID = 100, 102 StartTime = $StartTime EndTime = $EndTime Data = $TaskName } # Retrieve events $events = Get-WinEvent -FilterHashtable $filter | Select-Object TimeCreated, @{n='Action';e={$_.TaskDisplayName}} # Calculate time difference $timeDifference = New-TimeSpan -Start $StartTime -End $EndTime # Output event details $events
解决方案
核心要点:
- 同一个任务的单次执行实例,其启动(ID100)和完成(ID102)事件会共享相同的TaskInstanceId,需通过这个ID配对事件
- 事件自带的
TimeCreated属性就是任务实际启动/完成的时间,用这个属性计算时间差才准确
修改后的脚本:
# 变量定义 $TaskName = '\TestTask' $timeRangeStart = (Get-Date).AddDays(-1) $timeRangeEnd = Get-Date # 事件筛选条件 $filter = @{ LogName = 'Microsoft-Windows-TaskScheduler/Operational' ID = 100, 102 StartTime = $timeRangeStart EndTime = $timeRangeEnd Data = $TaskName } # 获取事件并提取关键属性:时间、事件ID、任务实例ID $events = Get-WinEvent -FilterHashtable $filter | ForEach-Object { [PSCustomObject]@{ TimeCreated = $_.TimeCreated EventId = $_.Id TaskInstanceId = $_.Properties[2].Value # 从事件属性中提取实例ID(索引从0开始) TaskName = $_.TaskDisplayName } } # 按任务实例ID分组,计算每组的执行时长 $executionResults = $events | Group-Object -Property TaskInstanceId | ForEach-Object { $startEvent = $_.Group | Where-Object { $_.EventId -eq 100 } $endEvent = $_.Group | Where-Object { $_.EventId -eq 102 } if ($startEvent -and $endEvent) { $duration = New-TimeSpan -Start $startEvent.TimeCreated -End $endEvent.TimeCreated [PSCustomObject]@{ TaskName = $startEvent.TaskName InstanceId = $_.Name StartTime = $startEvent.TimeCreated EndTime = $endEvent.TimeCreated ExecutionDuration = $duration DurationMinutes = [math]::Round($duration.TotalMinutes, 2) # 格式化分钟数,保留两位小数 } } elseif ($startEvent -and !$endEvent) { # 处理任务未完成的情况(仅存在启动事件) [PSCustomObject]@{ TaskName = $startEvent.TaskName InstanceId = $_.Name StartTime = $startEvent.TimeCreated EndTime = "任务仍在运行" ExecutionDuration = "未完成" DurationMinutes = "N/A" } } } # 输出结果 $executionResults
脚本关键说明:
$_.Properties[2].Value:任务计划操作事件的第3个属性(索引从0开始)就是TaskInstanceId,用来精准配对同一执行实例的启动/完成事件- 分组后分别筛选ID100和102的事件,避免不同执行实例的时间混乱
- 增加了任务未完成的判断逻辑,覆盖运维场景中的常见情况
- 输出结果包含格式化的分钟数,便于快速查看时长
内容的提问来源于stack exchange,提问作者TomMe
相关产品推荐
相关产品推荐

