Запустить код на закрытой консоли?

Я пишу приложение С#, которому необходимо загрузить файл, когда консоль закрыта (будь то с помощью кнопки X или компьютера).

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

AppDomain.CurrentDomain.ProcessExit += new EventHandler (OnExit);

Запускается только тогда, когда я вывожу команду exit на консоль, а не когда я нажимаю красную кнопку закрытия.

Пожалуйста, отвечайте только в том случае, если решение запускается как при закрытии консоли с помощью кнопки X, так и при выключении компьютера (обычно через Windows, я знаю, что вы не можете, если питание отключено xD).


person rshea0    schedule 27.03.2012    source источник
comment
извините, но есть сценарии, в которых ваш процесс убит, поэтому вы не можете заставить это работать во всех возможных случаях (возможно, вы видели это в Win7, где вы нажали завершение работы, и система сообщает вам, что некоторые процессы предотвращают завершение работы, и вы можете выбрать прекратить их)   -  person Random Dev    schedule 28.03.2012
comment
@CarstenKönig Я понимаю, что бывают такие ситуации, но я хочу, чтобы он хотя бы работал в обычном процессе завершения работы, если пользователь не принудительно закрывает приложения.   -  person rshea0    schedule 28.03.2012
comment
возможный дубликат stackoverflow.com/questions/474679/capture-console -выход-до-диез   -  person Sergey Berezovskiy    schedule 28.03.2012
comment
@lazyberezovsky Человек, ответивший на этот вопрос, сказал, что он не работает на Win7.   -  person rshea0    schedule 28.03.2012
comment
@ ryansworld10, поэтому вы выбрали копию этого ответа как правильный ответ?   -  person Sergey Berezovskiy    schedule 28.03.2012


Ответы (3)


Вы должны вызвать WIN32 API, для этого просто взгляните на этот пост здесь http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/707e9ae1-a53f-4918-8ac4-62a1eddb3c4a/

Я скопировал соответствующий код для вас оттуда:

class Program

{
    private static bool isclosing = false;

    static void Main(string[] args)
    {
        SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);

        Console.WriteLine("CTRL+C,CTRL+BREAK or suppress the application to exit");

        while (!isclosing) ;
    }

    private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
    {
        // Put your own handler here

        switch (ctrlType)
        {
            case CtrlTypes.CTRL_CLOSE_EVENT:
                isclosing = true;
                Console.WriteLine("Program being closed!");
                break;
        }

        return true;
    }

    #region unmanaged
    // Declare the SetConsoleCtrlHandler function
    // as external and receiving a delegate.

    [DllImport("Kernel32")]
    public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);

    // A delegate type to be used as the handler routine
    // for SetConsoleCtrlHandler.
    public delegate bool HandlerRoutine(CtrlTypes CtrlType);

    // An enumerated type for the control messages
    // sent to the handler routine.

    public enum CtrlTypes
    {
        CTRL_C_EVENT = 0,
        CTRL_BREAK_EVENT,
        CTRL_CLOSE_EVENT,
        CTRL_LOGOFF_EVENT = 5,
        CTRL_SHUTDOWN_EVENT
    }

    #endregion
}

Он делает именно то, что вам нужно.

Привет,

person Mario Fraiß    schedule 27.03.2012
comment
Что делает возвращаемый bool в делегате HandlerRoutine? - person mekb; 05.08.2019

Я также хотел бы предложить вам сохранить то, что вы хотите загрузить, на потом, чтобы у вас не было загруженных поврежденных / недействительных файлов. Таким образом, при следующем запуске приложения можно будет выполнить загрузку. Этот, по крайней мере, работает для выхода из системы / завершения работы:

SystemEvents.SessionEnding += (SystemEvents_SessionEnding);

private static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
{
    //code to run on when user is about to logoff or shutdown
}
person rtuner    schedule 27.03.2012

Может быть что-то вроде этого (при условии, что я правильно понял ваш запрос)

//get all command windows in the system
Process[] processes = Process.GetProcessesByName("cmd");


// find that one you interested in 
Process mypro;

Подпишитесь на событие Process.Exited, например

mypro.Exited += (s,e) =>
{
   //here upload the file
}

Должен работать на вас.

person Tigran    schedule 27.03.2012
comment
Я думаю, вы никогда не должны делать это так! потому что что, если есть более одного процесса с именем cmd. Если вы хотите подписаться на процесс, добавьте фильтрацию в код, например. имя окна процесса, а не самого процесса. - person Mario Fraiß; 28.03.2012
comment
@MarioFraiß: конечно. На самом деле история о том, как этот процесс cmd был обнаружен, была пропущена в моем посте. Вам нужен надежный ключ, чтобы найти запрошенный cmd.exe. - person Tigran; 28.03.2012