0

У меня есть простая библиотека, которая переопределяет события выключения консоли для выполнения различных задач перед закрытием. Это работает всякий раз, когда пользователь или внешняя программа закрывает консоль (ctrl + C, закрыть окно и т. Д.), Однако, когда консольное приложение использует Environment.Exit(), оно закрывается, не будучи признанным в качестве одного из событий выключения.Приложение для консоли C# Environment.Exit (0) не распознано как событие выключения

Вот код для обработчика завершения работы:

namespace ShutdownLibrary 
{ 
    public class ConsoleHandler 
    { 
     public bool ExitSystem = false; // Optional assistance for implementation. 

     [DllImport("Kernel32")] 
     private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add); 
     private delegate bool EventHandler(CtrlType sig); 
     private EventHandler _handler; 

     /// <summary> 
     /// Windows events to listen for. 
     /// </summary> 
     public enum CtrlType 
     { 
      CTRL_C_EVENT = 0, 
      CTRL_BREAK_EVENT = 1, 
      CTRL_CLOSE_EVENT = 2, 
      CTRL_LOGOFF_EVENT = 5, 
      CTRL_SHUTDOWN_EVENT = 6, 
     } 

     private bool Handler(CtrlType sig) 
     { 
      //Old .NET threading 
      var result = Task.Factory.StartNew<bool>(ShutdownTasks); 
      result.Wait(); 
      return result.Result; 
     } 

     /// <summary> 
     /// Starts an EventHandler for console windows & calls overridable ShutdownTasks() when console is closed by any means. 
     /// </summary> 
     public void StartShutdownEventHandler() 
     { 
      _handler += new EventHandler(Handler); 
      SetConsoleCtrlHandler(_handler, true); 
     } 


     /// <summary> 
     /// Overridable method for tasks to action before the program is disposed. 
     /// </summary> 
     /// <returns>True when complete. False when not implemented.</returns> 
     public virtual bool ShutdownTasks() 
     { 
      ExitSystem = false; 
      return false; 
     } 
    } 
} 

Само приложение потребляет отключение обработчика (ConsoleHandler), как это:

class ManagementServer : ServerManager 
    { 

     internal class ShutdownManager : ConsoleHandler 
     { 
      public override bool ShutdownTasks() 
      { 
       base.ShutdownTasks(); 
       for (var i = 5; i >= 0; i--) 
       { 
        Thread.Sleep(1000); 
        Log.WriteToLog(string.Format("Management Server Shutting down in {0}", i)); 
       } 
       Console.WriteLine("Good bye!"); 
       return true; 
      } 
     } 

    //Override from ServerManager 
    public override void ShutDownManagementServer() 
    { 
     base.ShutDownManagementServer(); 
     Environment.Exit(0); 
    } 

     static void Main(string[] args) 
     { 
      var sm = new ShutdownManager(); 
      sm.StartShutdownEventHandler(); 

      var manager = new ManagementServer(); 
      manager.StartServer(); 
     } 
    } 

Я думаю, что перечисление CtrlType в классе ConsoleHandler является главный виновник, но я не могу понять, какие значения отсутствуют.

Любые идеи?

+0

Уверенный, он был разработан, чтобы информировать вас о причинах, по которым ваше приложение будет прекращено, которые находятся вне вашего контроля. Как Ctrl + C, Ctrl + Break, пользователь нажимает кнопку «Закрыть», выдает или выключает компьютер. Другого пути вы не узнали. Вы, конечно, знаете, когда прекращаете себя, это не мешает вам напомнить об этом. Вы можете просто добавить другой CtrlType и сразу вызвать обработчик. –

+0

Отправьте элемент управления C себе ... затем он выключится с помощью вашего обработчика. – Hogan

+0

Некоторые говорят в этом ответе о том, почему Environment.Exit() не такая хорошая идея. http://stackoverflow.com/questions/10286056/what-is-the-command-to-exit-a-console-application-in-c – Hogan

ответ

-1

Выход не выполняет изящное завершение работы. Выход аналогичен вытягиванию шнура питания вашего ПК, тогда как start-> shutdown является изящным и информирует запущенные приложения, которые система закрывает.

Когда вы выдаете команду Exit, ни одно сообщение не отправляется в запущенные приложения. Вместо этого вам нужно использовать application.Shutdown.

см what's difference between Environment.Exit() and Application.Shutdown()?

редактировать: жаль, что не заметил, что это консольное приложение. Вместо этого вы можете попробовать обработать событие AppDomain.ProcessExit. Но, честно говоря, я не думаю, что это событие работает. Это событие известно не для запуска, если выдается команда грубых выходов (например, конечная задача). Выход очень груб.

+1

Application.Shutdown() не имеет смысла в приложении с консольным режимом. У него нет объекта Application, нет цикла диспетчера, который можно отключить. –

+0

@HansPassant прав, я не могу получить доступ к приложению Application.Shutdown() из контекста приложения консоли, поэтому подход кувалды с окружением. Exit() – Dezzamondo

+0

Это было бы плохо при выключении. Но я не думаю, что Exit будет работать, так как вам нужно уловить событие выключения, но Exit не должен поднять его. – user2880486