如何让任务调度程序从 powershell 脚本中检测失败的错误代码

Mic*_*ele 5 windows powershell exit-code taskscheduler

我有一些 powershell 脚本,当它们内部出现故障时,我试图将它们作为 Windows 任务调度程序中的失败状态触发。所以我在powershell脚本中做这样的事情。我尝试了 1 或 99 的退出代码,但看起来 Windows 任务调度程序并未将其视为失败状态。所以我的失败代码电子邮件不会发送出去通知我。

如何让任务调度程序看到我的 powershell 脚本失败?它总是有 129(创建的任务流程)、100(任务开始)、200(动作开始)、110(任务触发)、201(动作完成)、102(任务完成)的事件代码。

$global:ErrorStrings = New-Object System.Collections.Generic.List[System.Object] #I add strings onto the list as I find errors

$errorCodeAsString = ""
foreach ($item in $global:ErrorStrings.Members){
   $errorCodeAsString += (" " + $item + "..")
}
if($errorCodeAsString -ne "")
{
   write-output  "Error: $errorCodeAsString"
   Exit 99 #Exit 1 didn't cause task scheduler to see error at exit either
}
Exit 0
Run Code Online (Sandbox Code Playgroud)

我知道我的列表中充满了错误,因为我创建了它们来测试它。我检查了作为字符串的 errorCode 是一个长度并点击了退出 99 或 1。任务调度程序仍然显示正常的事件代码。

我有一个关于计划失败的电子邮件警报,由于事件代码没有显示失败,它永远不会触发发送我的电子邮件。这是 Windows 10,以防万一。

我一直在查看powershell 错误 sql任务调度程序成功错误提示技巧计划任务powershell 退出代码,但没有帮助。

powershell 脚本在任务调度程序中设置如下:

动作:启动一个程序

程序/脚本: PowerShell

添加参数: -ExecutionPolicy Bypass -File C:\Users\me\Documents\powershell\disasterBackup.ps1

HAL*_*256 9

第 1 部分是让 PowerShell 将正确的上次退出代码返回给任务计划程序。

这是 Task Scheduler 的特性之一。它只是报告说,是的,PowerShell.exe运行成功。问题是PowerShell.exe它不会报告退出代码,因为,是的PowerShell.exe,即使脚本没有正确运行。

我能够解决这个问题的方法是从运行带有-File不返回退出值的参数的脚本切换到-Command参数。这样我就可以PowerShell.exe通过使用$LASTEXITCODE值显式退出以正确的退出代码退出:

#Run Scheduled task with the following command

powershell.exe -Command ". C:\Scripts\RunScript.ps1; exit $LASTEXITCODE"
Run Code Online (Sandbox Code Playgroud)

所以在你的情况下,它将是:

powershell.exe -ExecutionPolicy Bypass -Command ". C:\Users\me\Documents\powershell\disasterBackup.ps1; exit $LASTEXITCODE"
Run Code Online (Sandbox Code Playgroud)

- - 编辑 - -

第 2 部分是在无法发送电子邮件或其他内容时在事件上触发计划任务。

任务计划程序的问题与我们退出 PowerShell 时遇到的问题相同。无论返回什么退出代码,任务总是记录事件 ID 201 - 操作已完成...这是正确的...无论如何,即使运行的作业在内部失败,任务也已完成。

进一步展望的记录事件的详细情况,我们可以看到ResultCodeEventData没有得到正确设置。因此,通过 GUI 过滤它是一项简单的工作,对吗?.... 不...除了 EventID 之外没有过滤器。现在我们必须编写一个自定义事件过滤器来触发基于ResultCode. 我们需要的 XML XPath 查询是这样的:

<QueryList>
  <Query Id="0" Path="Microsoft-Windows-TaskScheduler/Operational">
    <Select Path="Microsoft-Windows-TaskScheduler/Operational">
      *[System[(Level=4 or Level=0) and (EventID=201)]]
        and
      *[EventData[Data[@Name='ResultCode'] and (Data='2147942401')]]</Select>
  </Query>
</QueryList>
Run Code Online (Sandbox Code Playgroud)

所以为了分解它,我们想要:

Event log: Microsoft-Windows-TaskScheduler/Operational
Event Level: 4 or 0 = Information
Event ID: 201
And
Event Data: ResultCode = 2147942401
Run Code Online (Sandbox Code Playgroud)

如果我们将错误退出代码设置为 1,为什么是ResultCode = 2147942401?因为它实际上返回的0x1是十六进制0x80070001,它等于十进制2147942401。因此,您必须查看事件的详细信息才能找到“正确”的 ResultCode。

  • 这里有一些很棒的信息。请注意,您_可以_使`-File` 报告退出代码,但前提是显式调用的脚本使用`exit &lt;n&gt;` 退出脚本。另请注意,脚本可能会因 PowerShell 本地命令失败而失败,这不会反映在 `$LASTEXITCODE` 中。_0x1 是十六进制的 0x80070001_ 有点令人困惑:更准确地说,任务执行引擎通过与“0x80070000”进行位或运算来报告非零退出代码;要获取嵌入的退出代码,请使用“2147942401 -band -bnot 0x80070000”或相反地“1 -bor 0x80070000L” (2认同)