You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell捕获错误后重启进程失败:计划任务中进程未重启

进程重启失败问题排查与解决

环境配置

  • Windows计划任务运行PowerShell脚本
  • PowerShell脚本调用bat文件
  • bat文件运行.NET可执行文件

原脚本代码

$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "Console.bat"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = @("-s SomeArgument")

$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null   

$stdout=""

do
{
   $stdout += $p.StandardOutput.ReadLine()
}
while (!$p.HasExited)

if($stdout.Contains("Error while processing data"))
{
    Start-Sleep -Seconds 30;
    $p.Start() | Out-Null   
}

问题描述

通过计划任务运行脚本时,能看到cmd.exe、conhost.exe及.NET可执行文件进程。强制触发错误测试进程重启功能时,进程并未重启,仅conhost.exe停留30秒后关闭。


问题原因与解决方案

1. 无法复用已退出的Process对象

$p对应的进程退出后,该Process对象内部状态已标记为已退出,无法直接通过Start()方法重启。必须重新创建Process实例,或把启动逻辑封装为函数重复调用。

2. 标准输出读取可能导致死锁

仅同步读取StandardOutput但未处理StandardError,当进程往stderr输出内容且缓冲区满时,会导致进程阻塞无法正常退出,进而影响后续重启逻辑。

3. 计划任务工作目录问题

计划任务默认工作目录通常不是脚本所在目录,直接用相对路径调用Console.bat可能导致找不到文件,需指定绝对路径。

修正后的脚本

# 封装进程启动逻辑,避免重复代码
function Start-TargetProcess {
    $pinfo = New-Object System.Diagnostics.ProcessStartInfo
    # 替换为Console.bat的绝对路径
    $pinfo.FileName = "C:\Full\Path\To\Console.bat"
    $pinfo.RedirectStandardError = $true
    $pinfo.RedirectStandardOutput = $true
    $pinfo.UseShellExecute = $false
    $pinfo.Arguments = "-s SomeArgument"
    # 设置工作目录为bat文件所在目录,避免路径依赖问题
    $pinfo.WorkingDirectory = Split-Path $pinfo.FileName -Parent

    $p = New-Object System.Diagnostics.Process
    $p.StartInfo = $pinfo

    # 异步读取输出,避免死锁
    $stdoutBuilder = New-Object System.Text.StringBuilder
    $stderrBuilder = New-Object System.Text.StringBuilder
    $stdoutEvent = Register-ObjectEvent -InputObject $p -EventName OutputDataReceived -Action {
        $Event.MessageData.AppendLine($EventArgs.Data)
    } -MessageData $stdoutBuilder
    $stderrEvent = Register-ObjectEvent -InputObject $p -EventName ErrorDataReceived -Action {
        $Event.MessageData.AppendLine($EventArgs.Data)
    } -MessageData $stderrBuilder

    $p.Start() | Out-Null
    $p.BeginOutputReadLine()
    $p.BeginErrorReadLine()

    # 等待进程完全退出
    $p.WaitForExit()

    # 清理事件注册
    Unregister-Event $stdoutEvent.Id
    Unregister-Event $stderrEvent.Id

    # 返回输出内容,方便后续检查
    return @{
        StdOut = $stdoutBuilder.ToString()
        StdErr = $stderrBuilder.ToString()
    }
}

# 第一次启动进程
$runResult = Start-TargetProcess

# 同时检查标准输出和错误输出中的错误信息
if ($runResult.StdOut.Contains("Error while processing data") -or $runResult.StdErr.Contains("Error while processing data")) {
    Start-Sleep -Seconds 30
    # 重新启动进程
    Start-TargetProcess | Out-Null
}

额外注意事项

  • 确保计划任务的执行账户有足够权限启动目标进程,必要时勾选"不管用户是否登录都要运行",并配置正确的权限。
  • 可添加日志记录,将输出内容写入文件方便排查,比如在函数末尾加入$runResult.StdOut | Out-File "C:\Logs\process_log.log" -Append。

内容的提问来源于stack exchange,提问作者Luci C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 06:30:26