我们的客户有一些运行由任务计划程序激活的批处理作业的 Windows 2003 服务器。执行工作的实际程序是自定义的 .exe 进程,它们被聚合到 .cmd 脚本中,以便在预定的时间间隔到来时由任务计划程序一起启动它们。cmd 脚本中的行可能会或可能不会使用 Call 命令来启动单独的 .exe 程序。
在此设置中,任务计划程序有效地监控 cmd.exe,当使用进程资源管理器时,可以观察到子 .exe 进程停在 cmd.exe 进程树下。但是,当任务计划程序因超过允许的时间限制而杀死 cmd.exe 时,子 .exe 进程可能不会与其父进程一起被杀死并成为孤立的。这些进程无限期地停滞不前。由于 Process Explorer 中显示的进程线程的状态,我怀疑这些进程最终出错并弹出一个 .NET 调试器对话框(这些是 .NET 应用程序),因为批处理作业用户是单独的用户,所以无法看到该对话框帐户。
最初,当我在 Windows XP 工作站上调查此行为时,我观察到当任务计划程序确定时间到时,从我的测试 .cmd 脚本启动的子 .exe 进程确实与 cmd.exe 一起被杀死。我不可能孤立子进程。
基于一种预感,我最终转移到一台 Windows 2003 机器上进行测试。同样,子进程也会像我的工作站一样被终止。然后我的第二步是使用另一个用户帐户来运行计划任务。这一次, cmd.exe 在超过时间限制后被杀死,但子进程保持不变,就像我的客户在他们的生产服务器中观察到的一样。
如果我抢先登录该批处理用户帐户(恰好是另一个管理员帐户)以申请桌面会话,则来自我的测试 .exe 程序的任何错误或信息弹出窗口都将被路由并呈现在该桌面上,允许我查看实际的用户输出。如果我只在调度任务被调用后登录,桌面会话将不会“回收”现有进程的窗口;他们永远隐藏起来。
我的问题是,我在这里缺少什么条件会导致任务计划程序无法清除 cmd.exe 下的子进程?使用会导致这种行为的另一个帐户有什么特别之处,但在使用我当前的管理员帐户运行计划任务时没有?
尝试在命令行上使用“Taskkill /T”。(/T = “...终止指定进程和由它启动的任何子进程...”)
如果您有多个进程正在运行(我们通常运行 5 个或更多“powershell.exe”),则将“命令行”列添加到任务管理器的“详细信息”选项卡中。那应该清楚哪个进程 ID 是您要杀死的进程 ID
进程在 Windows 中是独立的 - 终止父进程不会自动终止子进程。
如果您认为这是由于弹出了调试器消息,您是否尝试过将代码包装在一个
try{}catch{}
块中并记录错误?否则,也许您可以做的是让进程写入
WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent())
我怀疑孩子们以某种方式将他们的特权级别升级到管理员,然后不能被父母杀死。
要在不修改代码的情况下对此进行测试,您可以编写另一个计划任务,尝试使用taskkill杀死其他进程。此计划任务应以管理员身份运行。如果可行,那么看起来这是一个安全问题。
如何使用pskill实用程序,它是 SysInternals 套件的一部分。该程序可以按名称杀死进程。我将添加一个计划任务,该任务将在您期望进程完成后几分钟运行,该任务将运行 pskill 来终止它们。
PSKill 也可以在您在命令行上提供的用户凭据下运行。
我不知道它会解决你的问题,但如果它与弹出框有关(它可能是 - 应用程序处于故障状态,并在不存在的用户决定如何处理时暂停) .
看看http://blogs.msdn.com/shawnfa/archive/2004/07/15/184490.aspx,看看你能不能摆脱那些盒子......