2009-05-18 16 views
6

.NETコンソールアプリケーションの終了を停止する方法はありますか?.netコンソールアプリケーションの終了を停止する

while (true) 
{ 
    string x = Console.ReadLine(); 
    StartLongRunningTaskOnSeparateThread(x); 
} 

問題は、それがコンソールウィンドウを閉じて(したがって、長時間実行されるタスクを遮断)することは可能だということです。私は、このパターンを次のアプリを持っています。コンソールアプリのForms.OnClosingイベントのイコールはありますか?

EDIT - 私は殺すことが不可能なものを作成しようとしていません。単に警告メッセージを送信するだけです。e..g「ねえ、私はまだやっていません。

EDIT2 - Ctrlキーを押しながら「x」ボタンを押して終了するのが重要です(私は​​を使用しました)。この目的のために、タスクマネージャーを起動させる人は誰でもプログラムを殺して、できるだけ多くの人にできることを望んでいるとします。また、エンドユーザーは誤って長時間実行していたタスクをキャンセルするよりもむしろ警告を表示することになります。

+0

EDIT2では、この場合、ウィンドウから「X」ボタンを削除するだけです。下記の私の更新された答えを見てください。 – beach

+0

@beachそれはうまく仕事をします。どうもありがとう。 – SillyMonkey

答えて

10

ここで私はこの問題を解決しようとしています。タスクマネージャーはまだアプリケーションを閉じることができます。しかし、私の考えは、それが閉鎖されているときに試してみて、それを再起動することでした。しかし、私はその部分を実装していませんでした。

次のプログラムは、CTRL-C & & CTRL-BREAKを検出し、今後も継続されます。

EDIT:私はアプリケーションを閉じてからユーザーを防ぐことはできませんでしょう "X" ボタン

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ComponentModel; 
using System.Runtime.InteropServices; 
using System.Diagnostics; 

namespace DoNotCloseMe 
{ 
    class Program 
    { 

     const string _title = "DO NOT CLOSE - Important Program"; 

     static void Main(string[] args) 
     { 

      Console.Title = _title; 

      IntPtr hMenu = Process.GetCurrentProcess().MainWindowHandle; 
      IntPtr hSystemMenu = GetSystemMenu(hMenu, false); 

      EnableMenuItem(hSystemMenu, SC_CLOSE, MF_GRAYED); 
      RemoveMenu(hSystemMenu, SC_CLOSE, MF_BYCOMMAND); 

      WriteConsoleHeader(); 

      //This function only seems to be called once. 
      //After calling MainLoop() below, CTRL-C && CTRL-BREAK cause Console.ReadLine() to return NULL 
      Console.CancelKeyPress += (sender, e) => 
      { 
       Console.WriteLine("Clean-up code invoked in CancelKeyPress handler."); 
       Console.WriteLine("Key Pressed: {0}", e.SpecialKey.ToString()); 
       System.Threading.Thread.Sleep(1000); 
       MainLoop(); 
       // The application terminates directly after executing this delegate. 
      }; 

      MainLoop(); 

     } 

     private static void MainLoop() 
     { 
      while (true) 
      { 
       WriteConsoleHeader(); 
       string x = Console.ReadLine(); 
       if (!String.IsNullOrEmpty(x)) 
       { 
        switch (x.ToUpperInvariant()) 
        { 
         case "EXIT": 
         case "QUIT": 
          System.Environment.Exit(0); 
          break; 
         default: 
          StartLongRunningTaskOnSeparateThread(x); 
          break; 
        } 

       } 
      } 
     } 

     private static void StartLongRunningTaskOnSeparateThread(string command) 
     { 
      var bg = new System.ComponentModel.BackgroundWorker(); 
      bg.WorkerReportsProgress = false; 
      bg.WorkerSupportsCancellation = false; 

      bg.DoWork += (sender, args) => 
      { 
       var sleepTime = (new Random()).Next(5000); 
       System.Threading.Thread.Sleep(sleepTime); 
      }; 


      bg.RunWorkerCompleted += (sender, args) => 
      { 
       Console.WriteLine("Commmand Complete: {0}", command); 
      }; 

      bg.RunWorkerAsync(); 

     } 

     private static void WriteConsoleHeader() 
     { 
      Console.Clear(); 
      Console.WriteLine(new string('*', Console.WindowWidth - 1)); 
      Console.WriteLine(_title); 
      Console.WriteLine(new string('*', Console.WindowWidth - 1)); 
      Console.WriteLine("Please do not close this program."); 
      Console.WriteLine("It is maintaining the space/time continuum."); 
      Console.WriteLine("If you close it, Q will not be happy and you will be assimilated."); 
      Console.WriteLine(new string('*', Console.WindowWidth - 1)); 
      Console.WriteLine("Development Mode: Use \"EXIT\" or \"QUIT\" to exit application."); 
      Console.WriteLine(new string('*', Console.WindowWidth - 1)); 
     } 

     #region "Unmanaged" 

     [DllImport("user32.dll")] 
     static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable); 

     [DllImport("user32.dll")] 
     static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); 

     [DllImport("user32.dll")] 
     static extern IntPtr RemoveMenu(IntPtr hMenu, uint nPosition, uint wFlags); 

     internal const uint SC_CLOSE = 0xF060; 
     internal const uint MF_GRAYED = 0x00000001; 
     internal const uint MF_BYCOMMAND = 0x00000000; 

     #endregion 
    } 
} 
+0

@SM - 答えに記載されています。しかし、私はあなたに攻撃の計画を与えました。 ;) – beach

+0

@SM - 「X」ボタンを削除しました。タスクマネージャはまだそれを殺すことができます。 – beach

+0

"X"ボタンはかなり効果的ですが、私の目的のためには必要なものでした。ありがとう。 – aboy021

0

コンソールアプリケーションのForms.OnClosingと同等の機能はありません。しかし、Forms.OnClosingでさえ、アプリケーションが終了するのを防ぐための絶対的な方法ではありません。私はタスクマネージャーでプログラムを見つけてそれを簡単に見つけることができます。これはForms.OnClosingトリックを完全にバイパスし、アプリケーションを慎重にシャットダウンします。これを防ぐためにできることは何もありません。

なぜこのようにしたいのか、もう少し詳しく説明できますか?

3

タスクマネージャをシャットダウンするだけでは十分ではありませんが、サービスとしてアプリケーションを作成していたら、少なくともデスクトップには魅力的な "x"人々はヒットする?

EDIT:あなたのコメントに基づいています。 書き換えられないユーザー入力を必要とするコンソールアプリケーションは、常に「x」を使用して閉じることができます。

サービスとしてのリライトは大きな仕事ではありません。サービスは実際には何らかのラッパーコードを持つ実行可能ファイル以上のものです。

難易度はユーザーの入力に伴います。しかし、長時間実行しているスレッドをサービスとして書くことはできますが、スレッドを実行するための命令を渡すためのコンソールアプリケーションを持つことができます。

また、「x」を押してしまっている人を偶然に止めたい場合は、コンソールアプリケーションの最初の10行を「重要な処理はしないでください!!」

+0

1.書き換えたくありません 2.サービスはユーザー入力が必要です。 – SillyMonkey

1

.NETコンソールアプリケーションの終了を停止する方法はありますか?

いいえcontrol-C(ブロックConsole.CancelKeyPressイベント参照)はブロックできますが、control-breakはブロックできません。

停止が難しいものが必要な場合は、Windowsサービスを作成するときに、停止するブロックを防ぐためのACL(システム...以外はシステムがシャットダウンできるようにする)を作成する必要があります。

追加:ユーザーの操作が必要な場合は、アプリケーションを2つの部分に分割します。実行中のサービスで、プロセス間のエントリポイントを公開します。インタラクティブ性を提供し、プロセス間通信を使用してサービスと通信するUI。

2

なぜ小さなWinformsフロントエンドを書いてみませんか?ユーザーが閉じるときに視覚的なフィードバックを提供する方が簡単です。最小化/最大化/閉じるボタンを無効にすることができます。

私は、あなたのものを実行できる超薄型winformsアプリを実行することに罰則はないということです。

私はあなたがWindows上にいると仮定しますが、これがMono.NETの場合はGTKなどを使用できます。

0

を削除しました。私がすることは、「これは数分かかるかもしれません...」と言うプロセスを開始するときに警告を出すことです。

次に殺すと決めたら、殺すでしょう。

個人的に私は、プロセスが私からの制御をあまりにも奪うと嫌いです。

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

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

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

    private static bool ConsoleCtrlCheck(CtrlTypes ctrlType) 
    { 
     Trace.WriteLine("** Received termination event : " + ctrlType.ToString()); 
     return true; 
    } 

    static void Main(string[] args) 
    { 

     SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true); 

    } 
関連する問題