如何使用PowerShell确定两个特定的Windows事件ID之间的时间差异。

huangapple go评论68阅读模式
英文:

How to use Powershell to determine the difference in time between two specific Windows Event IDs

问题

我正在寻找一种计算两个特定事件ID之间的时间差的方法,针对特定任务计划程序作业名称,在过去的24小时内。然后,如果时间太短(表示某些事情没有正常工作),或者如果运行了适当的时间,就可以触发某些操作来结束脚本。

我有一个脚本,仅提取了过去24小时内仅为一个作业的事件(代码如下)。

我无法弄清楚如何解析$events(仅包含过去24小时内的事件子集和该作业名称)以获取我的“开始”和“结束”时间,以便进行计算。

以下是我的输出示例,对于一个运行“成功”,但实际上发生了错误的作业 - 通常需要3-4分钟才能运行:


截止到08/03/2023 09:00:01:

MachineName TimeCreated         Id TaskDisplayName            
----------- -----------         -- ---------------            
Servername  8/3/2023 3:00:03 AM 102 Task completed             
Servername  8/3/2023 3:00:03 AM 201 Action completed           
Servername  8/3/2023 3:00:00 AM 200 Action started             
Servername  8/3/2023 3:00:00 AM 100 Task Started               
Servername  8/3/2023 3:00:00 AM 129 Created Task Process       
Servername  8/3/2023 3:00:00 AM 107 Task triggered on scheduler

有人能提供一些想法吗?我已经看了各种帖子,但没有得到任何思路。

我有一个Powershell脚本,我用它来每天提取特定任务计划程序作业的事件ID,然后将其附加到文本文件中。然后我有一个已知的良好ID列表,我会将其筛选出来,如果有一个不是“好”的事件ID列出来,那么它会给我发送一封电子邮件,表示发生了不寻常的事情。

以下是我用于指定任务名称、我的文本文件路径等的代码,但我希望重用$events变量,该变量应该包含所有内容:

英文:

I am looking to find a way to calculate the time difference between two specific event IDs, for a specific task scheduler job name, in the past 24 hours. Then I can trigger something if the time is too short (meaning something didn't work right), or if it ran for an appropriate amount of time, end the script.

I have a script that pulls just the events for just the one job, in just the last 24 hours (code is below).

I cannot figure out how to parse the $events (subset of events just for the last 24 hours and just for that job name) to get my "start" and "stop" time in order to make a calculation.

Example of my output for a job that ran "successfully" but something happened and it actually failed - it usually takes 3-4 minutes to run:


As of 08/03/2023 09:00:01 :

MachineName TimeCreated         Id TaskDisplayName            
----------- -----------         -- ---------------            
Servername  8/3/2023 3:00:03 AM 102 Task completed             
Servername  8/3/2023 3:00:03 AM 201 Action completed           
Servername  8/3/2023 3:00:00 AM 200 Action started             
Servername  8/3/2023 3:00:00 AM 100 Task Started               
Servername  8/3/2023 3:00:00 AM 129 Created Task Process       
Servername  8/3/2023 3:00:00 AM 107 Task triggered on scheduler

Can anyone provide some ideas? I've been through all sorts of posts and cannot get an idea.

I have a Powershell script that I use to pull the event IDs for a specific Task Scheduler job every day and then append that to a text file. I end up with a running history of those results.

I then have a list of known-good IDs that I filter out and if there is an event ID listed that is not "good" then it sends me an email that something out of the ordinary has happened.

Here is what I use as code to specify the task name, my text file path and such, but I was hoping to reuse the $events variable which should have everything in there:

Start-Transcript -Path "C:\Path\TextFile.txt"

$jobName = "TestJob";
$Date = Get-Date;

$file = "C:\Path$jobName.txt"
$file_path = Test-Path $file 
$pc = $_

#If file hasn't been created, create it
If ($file_path -ne $true){
    New-Item C:\Path$jobName.txt
}


#Filter xml to pull task scheduler events

#Task scheduler common event IDs to ignore (treat as good/success)
$notin = 100, 102, 107, 110, 129, 140, 200, 201;

try {

#Command to connect to remote Server (if needed)
#$events = Invoke-Command -ComputerName "servername.domain" -ScriptBlock {

#Command to execute locally
$events = Invoke-Command  -ScriptBlock {

#Pulls task scheduler, only events with the job (task's) name for events in the last 24 hours
$events = @(
 Get-WinEvent  -FilterXml @"
 <QueryList>
  <Query Id="0" Path="Microsoft-Windows-TaskScheduler">
   <Select Path="Microsoft-Windows-TaskScheduler/Operational">
    *[EventData/Data[@Name='TaskName']='$($args[0])'] and *[System[TimeCreated[timediff(@SystemTime) <= 86400000]]]
   </Select>
  </Query>
 </QueryList>
"@  -ErrorAction Stop
);
Return $events;

} -ArgumentList $jobName;
}

catch {
    Write-Warning -Message "Failed to query $($env:computername) because $($_.Exception.Message)" *> "C:\Path\errors.txt" 
    #If events exist from last 24 hours for this task, append the text (log) file with those events
}

   if ($events) {
    Add-Content C:\Path$jobName.txt "As of $Date :" -Encoding UTF8
    $events | Select MachineName,TimeCreated,Id,TaskDisplayName |  Out-File -Append C:\Path$jobName.txt -Encoding UTF8
   }else {
       Add-Content C:\Path$jobName.txt "No files found for last 24 hours as of $Date `r" -Encoding UTF8
   }

#Email function to email us but only email if there are tasks with codes other than the common success ones - only send an email if something is out of the ordinary   
Function email (){
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
    $EmailTo = "recipient@whatever.com";
    $EmailFrom = "sender@wherever.com";
    $Subject = "$jobName Failure";
    $Body = $ebody | Out-String;
    $SMTPServer = "smtp.office365.com"
    $SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body)
    $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587) 
    $SMTPClient.EnableSsl = $true 
    $SMTPClient.Credentials = New-Object System.Net.NetworkCredential("emailaddress", "password");
    $SMTPClient.Send($SMTPMessage)
    };
$ebody = @();
$ebody = $events | % { If ($_.id -notin $notin) {$_ | FL } }

If($ebody){email};

Stop-Transcript

答案1

得分: 0

这应该可以解决问题:

$LatestStart = $events | Where-Object Id -eq '100' | Sort-Object TimeCreated -Descending | Select-Object -First 1
$LatestEnd = $events | Where-Object {($_.ActivityId -eq  $LatestStart.ActivityId) -and ($_.Id -eq 102)}
$TimeTaken = New-TimeSpan -Start $LatestStart.TimeCreated -End $LatestEnd.TimeCreated

$TimeTaken 现在是最新事件所花费时间的时间跨度
最好的解决方案不是检查任务实际在做什么以确定它是否成功或者修复导致任务在显示已完成时实际上没有完成的问题吗
英文:

This should do the trick:

$LatestStart = $events | Where-Object Id -eq '100' | Sort-Object TimeCreated -Descending | Select-Object -First 1
$LatestEnd = $events | Where-Object {($_.ActivityId -eq  $LatestStart.ActivityId) -and ($_.Id -eq 102)}
$TimeTaken = New-TimeSpan -Start $LatestStart.TimeCreated -End $LatestEnd.TimeCreated

$TimeTaken is now the timespan for how long that latest event took.
Would the best solution not be to check whatever the task is actually doing though, to determine whether it was successful, or fixing the issue that is causing the task to show it completed fine when it didnt.

huangapple
  • 本文由 发表于 2023年8月4日 21:00:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76836166.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定