2009-05-18 21 views
6

क्या .NET कंसोल ऐप को बंद होने से रोकने का कोई तरीका है? मैं एक ऐप्लिकेशन है जो इस पद्धति का अनुसरण करता है:एक .net कंसोल ऐप को बंद होने से रोकें

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

समस्या यह है कि यह कंसोल विंडो बंद करने के लिए संभव है (और इसलिए लंबी चलने कार्य काट)। क्या कंसोल ऐप्स के लिए Forms.Onosing ईवेंट का एक समतुल्य है?

संपादित करें - मैं कुछ ऐसी चीज बनाने की कोशिश नहीं कर रहा हूं जो मारना असंभव है, बस एक चेतावनी संदेश दें ... "अरे, मैं अभी तक नहीं कर रहा हूं। क्या आप वाकई मुझे बंद करना चाहते हैं?"

EDIT2 - 'एक्स' बटन के माध्यम से एक असामयिक निकास को रोकने से Ctrl-C को अवरोधित करने से अधिक महत्वपूर्ण है (मैंने Console.TreatControlCAsInput = true; का उपयोग किया था)। इस उद्देश्य के लिए मान लें कि जो कोई भी टास्क मैनेजर को फायर करता है वह इस कार्यक्रम को इतना मारना चाहता है कि वे सक्षम होने के लायक हैं। और अंत उपयोगकर्ता अपने लंबे समय तक चलने वाले कार्य को गलती से रद्द करने की बजाय चेतावनी देखेंगे।

+0

प्रति EDIT2, उस स्थिति में, बस विंडो से "एक्स" बटन हटा दें। नीचे मेरा अद्यतन उत्तर देखें। – beach

+0

@beach जो अच्छी तरह से नौकरी करता है। बहुत धन्यवाद। – SillyMonkey

उत्तर

10

यहां इस समस्या को हल करने का मेरा प्रयास है। कार्य प्रबंधक अभी भी आवेदन बंद कर सकते हैं। लेकिन, मेरा विचार था कि इसे बंद होने पर कोशिश करें और पता लगाएं और फिर इसे फिर से लॉन्च करें। हालांकि, मैंने उस हिस्से को लागू नहीं किया था।

निम्नलिखित प्रोग्राम CTRL-C CTRL-BREAK का पता लगाएगा और आगे बढ़ेगा।

संपादित करें: निकाला गया "एक्स" बटन

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 - "एक्स" बटन हटा दिया गया। कार्य प्रबंधक अभी भी इसे मार सकता है। – beach

+0

"एक्स" बटन बहुत प्रभावी है, और मेरे उद्देश्यों के लिए यह केवल वही चीज़ थी जिसकी मुझे आवश्यकता थी। धन्यवाद। – aboy021

0

मुझे कंसोल एप्लिकेशन के लिए फॉर्म.ऑनक्लोज़िंग के किसी समकक्ष फ़ंक्शन के बारे में पता नहीं है। हालांकि फॉर्म। ऑनक्लोजिंग एक एप्लिकेशन को बंद होने से रोकने के लिए एक मूर्ख तरीका नहीं है। मैं बस कार्य प्रबंधक में प्रोग्राम को आसानी से ढूंढ सकता हूं और इसे मार सकता हूं। यह फ़ॉर्म को पूरी तरह से बाईपास करेगा और आपके आवेदन को बंद कर देगा। इसे रोकने के लिए आप कुछ भी नहीं कर सकते हैं।

क्या आप हमें ऐसा कुछ और संदर्भ दे सकते हैं कि आप ऐसा क्यों करना चाहते हैं?

3

यह स्पष्ट रूप से कार्य प्रबंधक के रूप में सरल नहीं है या एक बंद कार्य को रोकने के लिए पर्याप्त है, हालांकि, आप थे एक सेवा के रूप आवेदन तो लिखने के लिए कम से कम यह एक आकर्षक के साथ डेस्कटॉप पर बैठे नहीं किया जाएगा "x" लोगों के हिट करने के लिए?

संपादित करें: आपकी टिप्पणी के आधार पर। एक कंसोल ऐप जिसमें उपयोगकर्ता इनपुट की आवश्यकता होती है जिसे आप फिर से लिख नहीं सकते हैं, हमेशा "x" का उपयोग करके बंद हो जाएगा।

एक सेवा के रूप में पुनः लिखना एक बड़ा काम नहीं है। एक सेवा वास्तव में कुछ रैपर कोड के साथ निष्पादन योग्य से अधिक कुछ नहीं है।

कठिनाई उपयोगकर्ता इनपुट के साथ आता है। हालांकि, आप अपने लंबे चलने वाले धागे को एक सेवा के रूप में लिख सकते हैं, फिर भी थ्रेड चलाने के लिए निर्देश पास करने के लिए एक कंसोल ऐप है।

वैकल्पिक रूप से, अगर आप लोगों को "एक्स" दबाकर गलती से रोकना चाहते हैं, तो कंसोल ऐप की पहली 10 लाइनों को क्यों न भरें "महत्वपूर्ण प्रक्रिया बंद न करें !!"

+0

1. को फिर से लिखना नहीं चाहते 2. 2. उपयोगकर्ता इनपुट की आवश्यकता के अनुसार सेवा अच्छी नहीं है – SillyMonkey

1

वहाँ बंद किया जा रहा से एक .NET कंसोल अनुप्रयोग को रोकने के लिए कोई तरीका है?

नहीं, नियंत्रण-सी (Console.CancelKeyPress घटना देखें) ब्लॉक कर सकते हैं, लेकिन को नियंत्रित ब्रेक नहीं।

आप कुछ है कि आप एक एसीएल के लिए ब्लॉक इसे बंद कर दिया जा रहा है के साथ, एक Windows सेवा बनाने पर देखने की जरूरत है को रोकने के लिए बहुत मुश्किल है की जरूरत है (सिस्टम के अलावा ... इसलिए प्रणाली बंद कर सकते हैं) है।

अतिरिक्त: यदि उपयोगकर्ता इंटरैक्शन की आवश्यकता है, तो एप्लिकेशन को दो भागों में विभाजित करें। एक सेवा जो चलती रहती है, एक अंतर-प्रक्रिया प्रविष्टि बिंदु का खुलासा करती है। और एक यूआई जो अंतःक्रियाशीलता प्रदान करता है और सेवा के साथ संवाद करने के लिए अंतर-प्रक्रिया संचार का उपयोग करता है।

2

आप एक छोटे से Winforms फ्रंटएंड क्यों नहीं लिखते हैं? जब उपयोगकर्ता बंद हो रहा है तो दृश्य प्रतिक्रिया प्रदान करना आसान है।आप कम से कम/अधिकतम/बंद बटन अक्षम कर सकते हैं।

मेरा मतलब है, एक सुपरथिन Winforms ऐप चलाने में कोई दंड नहीं है जो आपकी सामग्री कर सकता है।

मुझे लगता है कि आप विंडोज पर हैं, लेकिन यदि यह मोनो.नेट था तो आप जीटीके या इसी तरह का उपयोग कर सकते थे।

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

    } 
संबंधित मुद्दे