从一组控制台应用程序中彻底查杀控制台应用程序

时间:2011-11-07 22:14:42

标签: c# wpf process

我有一个Windows窗体,可以使用

创建同一程序的多个控制台应用程序(它会多次调用program.exe)
process.start().  

我正在寻找一种方法来识别应用程序的特定运行并彻底杀死它(即干净地关闭program.exe的第5个进程,但让所有其他进程保持运行)。我能够通过启动进程时给出的ID识别program.exe的每个不同进程,但除了调用之外我无法以任何方式关闭应用程序

process.kill() 

不执行应用程序的干净关闭。

我相信我不能使用

process.CloseMainWindow()

因为应用程序没有窗口(它通过在后台运行的控制台运行)。在从正在运行的进程列表中选择要杀死的进程后,我希望通过单击GUI中的按钮来终止进程。

我之所以需要这个,是因为我需要关闭每个进程的所有线程和突出方面。

我按如下方式定义每个新流程,

Process process = new Process();
process.StartInfo = info;

ExecutionDetails details = new ExecutionDetails(run_id, process, info, session_type, strategy_type, name, ExecutionViewModel);

lock (_runs)
_runs.Add(run_id, details); // will throw on Add if duplicate id, prevent duplicate
ExecutionViewModel.NewRun(details); // add to the view model

process.Start();

其中run_id是标识每个进程的GUID。

在一个单独的类中,我有通过进程执行的代码,该代码仅通过启动程序的命令提示符引用(即调用程序,提供配置变量等)。

有什么方法可以干净地关闭流程吗?我想当我想要杀死进程时调用一个事件可能会有效,但到目前为止,由于我无法指定我想要关闭的进程,所以我无法使用该想法。

**编辑 - 我试图提出的事件处理代码,但它无法正常工作。

主窗口中的代码

 public void KillOne() {
     foreach (var details in _runs.Values) {
         if(details.IsSelected) {
             StrategyStateManager.SessionClosed(this, details.RunId);
                } } }

StrategyStateManager中的代码(用于保存程序中使用的变量和事件的中间类)

public delegate void StrategyCloseEventHandler(object sender, StrategyCloseEventArgs e);

    public static void SessionClosed(object sender, Guid id)
    {
        if(CloseSession != null)
            CloseSession(sender, new StrategyCloseEventArgs(id));
    }


public class StrategyCloseEventArgs : EventArgs
{

    private readonly Guid id;

    public StrategyCloseEventArgs(Guid run_id)
    {
        id = run_id;
    }

    public Guid GetRunID()
    {
        return id;
    }

}

主窗口正在启动的代码

 StrategyStateManager.CloseSession += (closeStrategy);

 void closeStrategy(object sender, StrategyCloseEventArgs e)
    {
        if (e.GetRunID() == run_id)
        {
            strategy.cleanupForShutdown();
            DBSaverSimple.shutdownAll();
            logger.Warn("Simulation run stopped by user");
        }
    }

2 个答案:

答案 0 :(得分:5)

立即想到的可能性是使用包含关闭消息的广播数据报以及要关闭的消息的进程ID。每个控制台进程都在公共端口上侦听广播数据报。当程序收到数据报时,它会解析数据,根据自己的进程ID检查传递的进程ID,如果匹配,程序将启动一个干净的关闭。

当然,这假定您已经为程序创建了一种干净利落的方式。

当然不保证能够接收广播数据报,但我的经验是它们在单个系统上是可靠的。如果遇到问题,可以让主程序发送数据报,等待一段时间查看程序是否已关闭,如果没有,则再次发送数据报。

另一种可能性是为您启动的每个进程创建一个名为EventWaitHandle的命令,并将该事件的名称传递给命令行上的控制台应用程序。然后,控制台程序可以有一个在该事件上执行WaitOne的线程。设置事件后,程序将启动干净关闭。这比广播数据报更可靠。当然,它每个进程使用另一个句柄,但除非你有数千个进程,否则这不会成为问题。

有关使用命名等待句柄在进程之间进行通信的示例,请参阅Send message from one running console app to another

答案 1 :(得分:2)

听起来好像你要在子流程运行的单独代码中有一个明确的状态,此时你希望该流程终止。为什么不在该代码路径的末尾调用Process.GetCurrentProcess().Kill();甚至Process.GetCurrentProcess().Close();

当它完成执行时会关闭/自杀,其余进程将继续按照他们认为合适的方式运行(直到他们也达到终止点)?