2011-11-07 65 views
5

我有一个创建同一程序的多个控制台应用程序在Windows窗体中的控制台应用程序(它调用的Program.exe任意次数)使用干净地杀死一组控制台应用程序

process.start(). 

我寻找一种方法来识别应用程序的特定运行并干净地杀死它(即干净地关闭program.exe的第5个进程,但保留所有其他进程运行)。我能够通过当过程被启动给予该ID来标识的Program.exe的每个不同的过程,但我无法关闭应用程序的任何其他方式比调用

process.kill() 

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

我相信,我不能使用

因为应用程序没有一个窗口(它是通过在后台运行的控制台运行)。我选择从正在运行的进程列表中选择要终止的进程后,通过单击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。

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

有没有什么办法可以干净地关闭进程?我在想,当我想要杀死进程的时候会有一个事件被调用,但是到目前为止,我还没有能够实现这个想法,因为我无法指定我想关闭哪个进程。

**编辑 - 我的代码事件处理,我试图impliment但它不工作。

代码在主窗口

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"); 
     } 
    } 

回答

4

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

这是假设,当然,你已经为节目本身干净地关闭创建的一种方式。

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

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

用于使用名为等待句柄的进程之间进行通信的一个例子见Send message from one running console app to another

+0

我为您推荐的EventWaitHandle Idea提供了很好的帮助。谢谢 – jwb555

+0

Downvoter?习惯于提供评论,给出downvote的理由。 –

1

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

这样,当它执行完毕,将关闭/杀本身,其余的进程将继续运行,因为他们认为合适的(直到他们也到达其终点)?

+0

当我想终止代码时,我没有确定的时间。终止由GUI中的按钮点击决定。如果我使用Process.Kill(),它将终止程序并且不执行干净的关闭,而Process.Close()实际上并不终止进程,它只是意味着释放进程上的“本地”视图以及关联的资源。 – jwb555

+0

你真的尝试过'process.CloseMainWindow()'吗?如果这是来自一个按钮按下,你肯定有一个主窗口。您也可以尝试'System.Exit()'关闭应用程序。如果在子流程中调用,我相信*它会给你你想要的。 – Kevek

+0

终止来自GUI,但实际进程没有在命令提示符中定义的窗口来启动进程。由于这个Process.CloseMainWindow()对进程没有任何作用。 System.exit()的工作,将其关闭,但我需要一个方法能够调用它在一个特定的过程,因为多会在同一时间运行,所以就需要一个事件或其他一些通知呼叫系统.Exit(),由于多重过程的情况,我一直无法实现。 – jwb555