Как отправить сигнал Ctrl + C на консольный процесс, созданный с флагом CreateNoWindow - PullRequest
1 голос
/ 10 августа 2011

Если я использую Process.Kill(), процесс прекращается. Тем не менее, я хотел бы прекратить его.

Я пытался с GenerateConsoleCtrlEvent(ConsoleCtrlEvent.CTRL_C, Process.Id) API, но безуспешно.

Если я установлю флаг False в CreateNoWindow, когда я посылаю Ctrl + C с клавиатуры, программа говорит "Caught signal: 2; Terminating". Так что дождитесь завершения сигнала «2».

Как я могу это сделать?

1 Ответ

1 голос
/ 21 декабря 2012

Есть решение.Я постараюсь описать это для вас:

Когда вы пишете приложение, которое оборачивает всю консоль - консоль не может получить управляющие коды по какой-то причине (вопрос идет в Microsoft), но консоль все еще может получатьэти события.Как?Из внешнего приложения.

Это код для cas.exe

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleAppStopper
{
    class cas
    {
        [STAThread]
        static void Main( string[] args )
        {
            if (args.Length < 2)
            {
                Help ();
                return;
            }
            int processId = int.Parse (args[0]);
            ConsoleCtrlEvent CtrlEvent = (ConsoleCtrlEvent)int.Parse(args[1]);

            FreeConsole ();
            AttachConsole (processId);
            GenerateConsoleCtrlEvent (CtrlEvent, 0);
        }

        static void Help()
        {
            Console.BackgroundColor = ConsoleColor.Black;
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            Console.WriteLine ("Console Application Eventer(Stopper)");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine ("cas.exe ProcessId ControlEvent");
            Console.WriteLine ("Events:");
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine ("\tCTRL_C - 0");
            Console.WriteLine ("\tCTRL_BREAK - 1");
            Console.WriteLine ("\tCTRL_LOGOFF - 5");
            Console.ResetColor ();
        }

        public enum ConsoleCtrlEvent
        {
            CTRL_C = 0, // From wincom.h
            CTRL_BREAK = 1,
            CTRL_CLOSE = 2,
            CTRL_LOGOFF = 5,
            CTRL_SHUTDOWN = 6
        }
        [DllImport ("kernel32.dll")]
        static extern bool GenerateConsoleCtrlEvent( ConsoleCtrlEvent sigevent,
        int dwProcessGroupId );

        [DllImport ("kernel32.dll")]
        static extern bool FreeConsole();

        [DllImport ("kernel32.dll")]
        static extern bool AttachConsole( int dwProcessId ); 
    }
}

и как его использовать:

public void SendConsoleEvent( ConsoleCtrlEvent ev )
{
    if (!Running)
        return;

    try
    {
        String current_dir = System.Environment.CurrentDirectory;
        String stopper = "cas.exe";
        String args = pr.Id + " " + (int)ev;

        CommandExecutor ex = new CommandExecutor (null, null);
        ex.Start (current_dir, stopper, args);
        // sometimes stop prevent CAS do work. just throw cas and forget about
        //Timer.DelayCall (TimeSpan.FromSeconds (10), ex.Stop);
        //ex.Stop ();
    }
    catch (Exception e)
    {
        Log ("SendConsoleEvent: " + e.ToString ());
    }
}

Здесь CommandExecutor мойрезьбовая оболочка вокруг процесса.pr.Id - это идентификатор ранее запущенного с помощью консоли Process (куда нам нужно отправить наш CTRL_C или другие события

...