干净杀死一组控制台应用程序内的控制台应用程序 [英] Cleanly killing a console application from within a group of console applications

查看:101
本文介绍了干净杀死一组控制台应用程序内的控制台应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经创建同一程序的多个控制台应用程序Windows窗体使用(它调用的Program.exe任意次数)

 的Process.Start()。 



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

  process.kill()

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



我相信我能不能用



  process.CloseMainWindow() 

因为应用程序没有一个窗口(它是通过在后台运行的控制台中运行) 。我期待通过点击我的GUI按钮来终止这些进程我选择从正在运行的进程的列表被杀后工序。



之所以我需要的,这是因为我需要关闭所有线程,它关闭之前每个进程的未决问题。



我定义每一个新的进程如下,

 工艺过程=新工艺(); 
process.StartInfo =信息;

ExecutionDetails细节=新ExecutionDetails(run_id,流程,信息,session_type,STRATEGY_TYPE,名称,ExecutionViewModel);

锁(_runs)
_runs.Add(run_id,详细说明); //将抛出添加如果重复ID,防止重复
ExecutionViewModel.NewRun(详细信息); //添加到视图模型

的Process.Start();



在哪里run_id是标识每个进程GUID。



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



有什么办法,我可以干净地关闭过程?我在想,有当我要杀掉该进程可能会奏效,但到目前为止我还没有能够得到这个想法的工作,因为我不能指定我想这过程中关闭。

$被称为事件b
$ b

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



代码在主窗口

 公共无效KillOne(){
的foreach(在_runs.Values VAR细节){
如果(details.IsSelected){
StrategyStateManager.SessionClosed(这一点,details.RunId);
}}}

守则StrategyStateManager(用于保存变量和事件使用的中产阶级程序)

 公共委托无效StrategyCloseEventHandler(对象发件人,StrategyCloseEventArgs E); 

公共静态无效SessionClosed(对象发件人,发送的Guid ID)
{
如果(CloseSession!= NULL)
CloseSession(发件人,新StrategyCloseEventArgs(ID));
}


公共类StrategyCloseEventArgs:EventArgs的
{

私人只读的Guid ID;

公共StrategyCloseEventArgs(GUID run_id)
{
ID = run_id;
}

公众的Guid GetRunID()
{
返回ID;
}

}

代码的过程,正在启动通过主窗口

  StrategyStateManager.CloseSession + =(closeStrategy); 

无效closeStrategy(对象发件人,StrategyCloseEventArgs E)
{
如果(e.GetRunID()== run_id)
{
strategy.cleanupForShutdown( );
DBSaverSimple.shutdownAll();
logger.Warn(模拟运行用户停止);
}
}


解决方案

的这立即想到可能是使用一个包含关闭消息以及要关闭一个进程id广播数据报。每一个控制台进程侦听公共端口的广播数据包。当程序接收到一个数据包时,它分析数据,会针对其自身的进程ID传递的进程id,如果他们匹配,程序启动正常关机。



这是假设,当然,你已经创建了程序自行关闭干净的方法。



广播数据报不保证收到的,当然,但我的经验是,他们是在单个系统上可靠。如果你碰到一个问题,你可以有你的主要程序来发送数据报,等待一段时间,看看该程序已关闭,如果没有的话再次发送数据包。



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



请参阅发送从一个运行控制台应用程序的消息到另一个为使用命名的一个例子等待处理进程间通信。


I have a windows form that creates multiple console applications of the same program (it calls program.exe any number of times) using

process.start().  

I am looking for a way to identify a specific running of the application and kill it cleanly (ie cleanly close the 5th process of program.exe but leave all other processes running). I am able to identify each different process of program.exe through ids that were given when the processes were started, but I am unable to close the application any way other than calling

process.kill() 

which does not perform a clean close of the application.

I believe that I cannot use

process.CloseMainWindow()

since the application does not have a window (it is run through a console that runs in the background). I am looking to kill the processes by clicking a button in my GUI after I select the process to be killed from a list of the processes that are running.

The reason why I need this is because I need to close all threads and outstanding aspects of each process before it closes.

I define each new process as follows,

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();

Where run_id is a GUID that identifies each process.

In a seperate class I have the code that is executed through the process which is only referenced through the command prompt that starts the program (ie calls program, provides config variables, etc).

Is there any way that I can close the processes cleanly? I was thinking that having an event that is called when I want to kill the process might work but so far I have not been able to get that idea to work since I am unable to specify which process I want closed.

** EDIT - My code for the event handling that I have tried to impliment but it is not working.

Code In Main Window

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

Code in StrategyStateManager (Middle class used to hold variables and events to use in program)

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

}

Code in process that is being started by main window

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

解决方案

The possibility that comes immediately to mind is to use a broadcast datagram that contains a close message and the process id of the one that you want closed. Each of the console processes listens for broadcast datagrams on a common port. When the program receives a datagram, it parses the data, checks the passed process id against its own process id, and if they match, the program initiates a clean shutdown.

This assumes, of course, that you have created a way for the program to shut itself down cleanly.

Broadcast datagrams aren't guaranteed to be received, of course, but my experience has been that they're reliable on a single system. If you run into a problem, you could have your main program send the datagram, wait some period of time to see if the program has shut down, and if not then send the datagram again.

Another possibility is to create a named EventWaitHandle for each process that you start, passing the name of that event to the console application on the command line. The console program could then have a thread that does a WaitOne on that event. When the event is set, the program initiates a clean shutdown. This is more reliable than the broadcast datagram. Sure, it uses another handle per process, but that won't be a problem unless you have thousands of processes.

See Send message from one running console app to another for an example of using a named wait handle to communicate between processes.

这篇关于干净杀死一组控制台应用程序内的控制台应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆