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