【问题标题】:How get task scheduler to detect failed error code from powershell script如何让任务调度程序从 powershell 脚本中检测失败的错误代码
【发布时间】:2019-05-22 02:35:14
【问题描述】:

我有一些 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

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

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

我一直在查看powershell errors sqltask scheduler success errortips tricks scheduled taskspowershell exit code,但没有帮助。

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

动作:启动程序

程序/脚本: PowerShell

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

【问题讨论】:

    标签: windows powershell exit-code taskscheduler


    【解决方案1】:

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

    这是任务计划程序的特点之一。它只是报告,是的,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"
    

    所以你的情况是:

    powershell.exe -ExecutionPolicy Bypass -Command ". C:\Users\me\Documents\powershell\disasterBackup.ps1; exit $LASTEXITCODE"
    

    --- 编辑----

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

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

    进一步查看记录事件的详细信息,我们可以看到EventData 中的ResultCode 确实设置正确。因此,通过 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>
    

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

    Event log: Microsoft-Windows-TaskScheduler/Operational
    Event Level: 4 or 0 = Information
    Event ID: 201
    And
    Event Data: ResultCode = 2147942401
    

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

    【讨论】:

    • 如果我使用 -Command 我是否还必须使用启动程序/脚本运行:Powershell?
    • 我尝试使用 Cmd 和 Powershell 的启动程序/脚本。当我将 Cmd 与您为我的案例/添加的参数显示的内容一起使用并运行它时,任务挂起并且无法在正常时间完成,因此我不得不终止它。当我像以前一样使用 PowerShell 时,它会在正常时间内完成 taskScheduler 中的正常事件,但没有失败退出代码。
    • 是的。您的程序/脚本仍然是 PowerShell.exe 您只是将参数更改为使用 -Command
    • 这里有一些很棒的信息。请注意,您可以-File 报告退出代码,但前提是调用的脚本显式使用exit &lt;n&gt; 退出脚本。另请注意,由于 PowerShell 原生命令失败,脚本可能会失败,这不会反映在 $LASTEXITCODE 中。 0x1 是十六进制的 0x80070001 有点令人困惑:更准确地说,任务执行引擎通过与0x80070000 进行位或运算来报告非零退出代码;要获取嵌入的退出代码,请使用2147942401 -band -bnot 0x80070000,或者相反,使用1 -bor 0x80070000L
    • 我很高兴您找到了解决方法,@Michele,但只是澄清一下:如果退出代码是 99Last Run Result 列应该显示 (0x63)。如果它显示(0x1),也许您使用-Command 而不是-File 运行脚本,或者您的脚本当前使用exit 1。只能选择标准字段作为显示列,ResultCode不是标准字段;它嵌入在与事件201 关联的特定于事件实例的自定义事件数据中。
    【解决方案2】:

    我要做的是将计划任务附加到失败的事件中,以便在发生这种情况时引发计划任务。

    【讨论】:

      【解决方案3】:

      查找所有失败任务时,HAL9256 的回答对我不起作用

      当我将他的 XML 转换为搜索所有非零返回码时,它最终匹配了所有返回码。零和非零都一样

      *[EventData[Data[@Name='ResultCode'] and (Data!='0')]]
      

      相反,我创建了一个带有“事件”触发器和以下自定义 xml 的任务:

      <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"]!=0)]] </Select>
        </Query>
      </QueryList>
      

      并运行以下 powershell 脚本

      Send-MailMessage -To -Subject "我的主题" -Body "其中一个任务失败。请登录服务器并查看事件日志详细信息以找出哪个任务失败" -SmtpServer mail.company.com -From server@company.com

      【讨论】:

        【解决方案4】:

        我知道这是事后诸葛亮,但我最终为此做的是,当我的 powershell 脚本出现故障时,我直接从它调用了一个电子邮件脚本。

        【讨论】:

          猜你喜欢
          • 2018-06-10
          • 2019-10-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-03-19
          • 2013-02-18
          相关资源
          最近更新 更多