2009-05-01 10 views
70

मैं (अतीत में) है लिखा पार मंच (विंडोज/यूनिक्स) अनुप्रयोगों, जो जब कमांड लाइन से शुरू कर दिया, एक उपयोगकर्ता के द्वारा लिखा गया Ctrl संभाला - एक ही तरीके से सी संयोजन (यानी समाप्त करने के लिए आवेदन साफ ​​से)।क्या मैं विंडोज़ पर एक एप्लीकेशन के लिए एक ctrl-c (SIGINT) भेज सकता हूं?

यह Windows पर संभव है एक Ctrl भेजने के लिए - सी अनुरोध करने के लिए है कि यह सफाई से समाप्त (यह संसाधनों को साफ़ रखने के लिए आदि का अवसर देने के) एक और (असंबद्ध) प्रक्रिया से एक प्रक्रिया के लिए/SIGINT/बराबर ?

+0

मैं जावा सेवा प्रक्रियाओं के लिए Ctrl-C भेजने सिर्फ threaddumps प्राप्त करने के लिए में रुचि थी के रूप में CtrlCSender चलाता है। ऐसा लगता है कि इस विशिष्ट मामले के लिए 'jstack' का विश्वसनीय रूप से उपयोग किया जा सकता है: https://stackoverflow.com/a/47723393/603516 – Vadzim

उत्तर

25

निकटतम जो मैं समाधान में आया हूं वह SendSignal तृतीय पक्ष ऐप है। लेखक स्रोत कोड और निष्पादन योग्य सूचीबद्ध करता है। मैंने सत्यापित किया है कि यह 64-बिट विंडोज़ (32-बिट प्रोग्राम के रूप में चल रहा है, एक और 32-बिट प्रोग्राम को मार रहा है) के तहत काम करता है, लेकिन मुझे पता नहीं चला कि विंडोज प्रोग्राम में कोड को कैसे एम्बेड किया जाए (या तो 32-बिट या 64-बिट)।

यह कैसे काम करता:

ज्यादा डीबगर में चारों ओर से खुदाई करने के बाद मुझे पता चला कि प्रवेश बिंदु है कि वास्तव में ctrl-तोड़ की तरह एक संकेत के साथ जुड़े व्यवहार करता है kernel32 है CtrlRoutine!। फ़ंक्शन में थ्रेडप्रोक के समान प्रोटोटाइप था, इसलिए इसे कोड इंजेक्ट किए बिना सीधे CreateRemoteThread के साथ उपयोग किया जा सकता है। हालांकि, यह एक निर्यातित प्रतीक नहीं है! यह विंडोज के विभिन्न संस्करणों पर अलग-अलग पतों (और यहां तक ​​कि अलग-अलग नाम भी हैं) पर है। क्या करें?

यहां समाधान है जो मैं अंत में आया था। मैं अपने ऐप के लिए एक कंसोल ctrl हैंडलर स्थापित करता हूं, फिर मेरे ऐप के लिए एक ctrl-break सिग्नल उत्पन्न करता हूं। जब मेरे हैंडलर को बुलाया जाता है, तो मैं कर्नेल 32 को पास पैरामीटर को खोजने के लिए स्टैक के शीर्ष पर वापस देखता हूं! बेस थ्रेडस्टार्ट। मैं पहला पैरा लेता हूं, जो धागे का वांछित प्रारंभ पता है, जो कर्नेल 32 का पता है! CtrlRoutine। फिर मैं अपने हैंडलर से लौटता हूं, यह दर्शाता है कि मैंने सिग्नल संभाला है और मेरा ऐप समाप्त नहीं किया जाना चाहिए। मुख्य धागे में वापस, मैं kernel32 के पते तक प्रतीक्षा करता हूं! CtrlRoutine पुनर्प्राप्त किया गया है। एक बार मुझे यह मिल गया, मैं खोज प्रक्रिया में एक दूरस्थ धागा खोज के साथ पता चला। इससे लक्ष्य प्रक्रिया में ctrl हैंडलर का मूल्यांकन किया जा सकता है जैसे कि ctrl-break दबाया गया था!

अच्छी बात यह है कि केवल लक्ष्य प्रक्रिया प्रभावित होती है, और किसी भी प्रक्रिया (यहां तक ​​कि एक खिड़की वाली प्रक्रिया) को लक्षित किया जा सकता है। एक नकारात्मक बात यह है कि मेरे छोटे ऐप को बैच फ़ाइल में उपयोग नहीं किया जा सकता है, क्योंकि यह कर्नेल 32 के पते को खोजने के लिए ctrl-break ईवेंट भेजता है जब यह इसे मार देगा! CtrlRoutine।

(start के साथ में आगे अगर यह एक बैच फ़ाइल में चल रहा है।)

+1

+1 - लिंक किया गया कोड Ctrl-C की बजाय Ctrl-Break का उपयोग करता है लेकिन इसके चेहरे पर (GenerateConsoleCtrlEvent के लिए प्रलेखन को देखकर) Ctrl-C के लिए अनुकूलित किया जा सकता है। –

+5

वास्तव में आपके लिए यह करने के लिए एक फ़ंक्शन है, lol, "GenerateConsoleCtrlEvent"। देखें: http://msdn.microsoft.com/en-us/library/ms683155(v=vs.85).aspx यहां मेरा उत्तर भी देखें: http://serverfault.com/a/501045/10023 – Triynko

+0

गिथब लिंक उपर्युक्त उत्तर से संबंधित: https://github.com/walware/statet/tree/master/de.walware.statet.r.console.core/win32 – meawoppl

6

संपादित करें:

एक जीयूआई अनुप्रयोग, "सामान्य" विंडोज विकास में इस संभाल करने के लिए प्रक्रिया की मुख्य विंडो के लिए एक WM_CLOSE संदेश भेजने के लिए किया जाएगा जिस तरह से है।

कंसोल ऐप के लिए, आपको CTRL_C_EVENT जोड़ने के लिए SetConsoleCtrlHandler का उपयोग करने की आवश्यकता है।

यदि एप्लिकेशन इसका सम्मान नहीं करता है, तो आप TerminateProcess पर कॉल कर सकते हैं।

+0

मैं इसे कमांड लाइन ऐप (कोई विंडो नहीं) में करना चाहता हूं। TerminateProcess एक बल मारने की तंत्र है (सिगकिल के समान) इसलिए टर्मिनिंग एप्लिकेशन को साफ करने का कोई मौका नहीं देता है। –

+0

@ मैथ्यू मर्डोक: कंसोल ऐप में इसे कैसे संभालना है, इस बारे में जानकारी शामिल करने के लिए अपडेट किया गया।आप एक ही तंत्र के माध्यम से विंडोज शटडाउन, या कंसोल बंद, आदि सहित अन्य घटनाओं को भी पकड़ सकते हैं। पूर्ण विवरण के लिए एमएसडीएन देखें। –

+0

@ रीड कॉपसी: लेकिन मैं इसे एक अलग प्रक्रिया से शुरू करना चाहता हूं। मैंने GenerateConsoleCtrlEvent (SetConsoleCtrlHandler से संदर्भित) पर एक नज़र डाली है, लेकिन ऐसा लगता है कि प्रक्रिया समाप्त होने पर प्रक्रिया को समाप्त करने की प्रक्रिया के समान प्रक्रिया 'प्रक्रिया समूह' में है ... कोई विचार? –

15

मुझे लगता है कि मैं इस सवाल पर देर से एक सा कर रहा हूँ, लेकिन मैं एक ही समस्या हो रही किसी के लिए वैसे भी कुछ लिखेंगे। यह वही जवाब है जैसा मैंने this प्रश्न दिया था।

मेरी समस्या यह थी कि मैं अपने आवेदन को जीयूआई एप्लीकेशन बनना चाहता हूं लेकिन निष्पादित प्रक्रियाओं को बिना किसी इंटरैक्टिव कंसोल विंडो के पृष्ठभूमि में चलाया जाना चाहिए। मुझे लगता है कि जब यह प्रक्रिया एक कंसोल प्रक्रिया है तो यह समाधान भी काम करना चाहिए। हालांकि आपको "CREATE_NO_WINDOW" ध्वज को हटाना पड़ सकता है।

मैं एक रैपर ऐप के साथ GenerateConsoleCtrlEvent() का उपयोग करके इसे हल करने में कामयाब रहा। मुश्किल हिस्सा यह है कि दस्तावेज़ीकरण वास्तव में स्पष्ट नहीं है कि इसका उपयोग कैसे किया जा सकता है और इसके साथ नुकसान।

मेरा समाधान here का वर्णन करने पर आधारित है। लेकिन इससे वास्तव में सभी विवरणों को और त्रुटि के साथ समझाया नहीं गया था, इसलिए यहां काम करने के तरीके के बारे में विवरण दिया गया है।

एक नया सहायक एप्लिकेशन "Helper.exe" बनाएं। यह एप्लिकेशन आपके एप्लिकेशन (अभिभावक) और उस बच्चे की प्रक्रिया के बीच बैठेगा जिसे आप बंद करना चाहते हैं। यह वास्तविक बाल प्रक्रिया भी बनाएगा। आपके पास यह "मध्य व्यक्ति" प्रक्रिया होनी चाहिए या जेनरेट कंसोलक्यूटरइवेंट() विफल हो जाएगी।

माता-पिता से सहायक प्रक्रिया में संवाद करने के लिए किसी प्रकार की आईपीसी तंत्र का उपयोग करें कि सहायक को बाल प्रक्रिया को बंद करना चाहिए। जब सहायक को यह ईवेंट मिलता है तो यह "GenerateConsoleCtrlEvent (CTRL_BREAK, 0)" कहता है जो स्वयं और बच्चे की प्रक्रिया को बंद कर देता है। मैंने इस घटना के लिए एक इवेंट ऑब्जेक्ट का इस्तेमाल किया जो माता-पिता को पूरा करता है जब वह बाल प्रक्रिया को रद्द करना चाहता है।

अपने Helper.exe को बनाने के लिए इसे CREATE_NO_WINDOW और CREATE_NEW_PROCESS_GROUP के साथ बनाएं। और जब बच्चे की प्रक्रिया बनाते हैं तो इसे कोई झंडे (0) के साथ बनाते हैं जिसका अर्थ है कि यह कंसोल को अपने माता-पिता से प्राप्त करेगा। ऐसा करने में विफल होने से यह घटना को अनदेखा कर देगा।

यह बहुत महत्वपूर्ण है कि प्रत्येक चरण इस तरह किया जाता है। मैं सभी अलग-अलग प्रकार के संयोजनों की कोशिश कर रहा हूं लेकिन यह संयोजन एकमात्र ऐसा काम करता है जो काम करता है। आप CTRL_C ईवेंट नहीं भेज सकते हैं। यह सफलता वापस कर देगा लेकिन प्रक्रिया से अनदेखा कर दिया जाएगा। CTRL_BREAK एकमात्र ऐसा काम करता है जो काम करता है। वास्तव में कोई फर्क नहीं पड़ता क्योंकि वे दोनों अंत में ExitProcess() को कॉल करेंगे।

आप जेनरेट कंसोलकूटइवेंट() को बाल प्रक्रिया आईडी की एक प्रक्रिया समूह आईडी के साथ भी कॉल नहीं कर सकते हैं, जिससे सहायक प्रक्रिया को सीधे जारी रखने की इजाजत मिलती है। यह भी असफल हो जाएगा।

मैंने पूरे दिन इस काम को पाने की कोशिश की। यह समाधान मेरे लिए काम करता है लेकिन अगर किसी को जोड़ने के लिए कुछ और है तो कृपया करें। मैं पूरी तरह से समस्याओं के साथ बहुत सारे लोगों को खोजने के लिए गया लेकिन समस्या का कोई निश्चित समाधान नहीं था। कैसे उत्पन्न करें CononCtrlEvent() काम भी थोड़ा अजीब है, इसलिए यदि कोई इस पर अधिक जानकारी जानता है तो कृपया साझा करें।

+3

के लिए दस्तावेज़ देखें! यह विंडोज एपीआई का एक और उदाहरण है जो इतनी भयानक गड़बड़ है। – vitaut

6

किसी भी तरह GenerateConsoleCtrlEvent() यदि आप इसे किसी अन्य प्रक्रिया के लिए कहते हैं तो वापसी त्रुटि, लेकिन आप अन्य कंसोल एप्लिकेशन से जुड़ सकते हैं और सभी बाल प्रक्रियाओं को ईवेंट भेज सकते हैं।

void SendControlC(int pid) 
{ 
    AttachConsole(pid); // attach to process console 
    SetConsoleCtrlHandler(NULL, TRUE); // disable Control+C handling for our app 
    GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); // generate Control+C event 
} 
+0

और नियंत्रण कैसे वापस करें? और फिर मैं नियंत्रण-सी, स्टॉपर प्रोग्राम भेजता हूं, लेकिन मैं उसके हाथों से कुछ भी नहीं कर सकता। –

+0

नियंत्रण कहां वापस करें? – KindDragon

+0

मुझे लगता है कि आप अपने हैंडलर को हटाने के लिए SetConsoleCtrlHandler (NULL, FALSE) को कॉल करते हैं, विभिन्न अन्य प्रतिक्रियाएं देखें। – rogerdpack

43

मैंने इस विषय के आसपास कुछ शोध किया है, जो मुझे अनुमानित से अधिक लोकप्रिय साबित हुआ है। KindDragon का जवाब मुख्य बिंदुओं में से एक था।

मैंने विषय पर longer blog post लिखा और एक कामकाजी डेमो प्रोग्राम बनाया, जो कि कुछ अच्छे फैशन में कमांड लाइन एप्लिकेशन को बंद करने के लिए इस प्रकार के सिस्टम का उपयोग करके प्रदर्शित करता है। उस पोस्ट में बाहरी लिंक सूचीबद्ध हैं जिन्हें मैंने अपने शोध में उपयोग किया था।

संक्षेप में, उन डेमो कार्यक्रमों निम्न कार्य करें:

  • प्रारंभ एक दृश्य खिड़की नेट का उपयोग कर के साथ एक कार्यक्रम है,, PInvoke साथ छिपाने 6 सेकंड के लिए चलाने के लिए, PInvoke साथ दिखाने के लिए, नेट के साथ बंद करो।
  • 6 सेकंड के लिए चलाने के नेट का उपयोग कर एक खिड़की के बिना एक कार्यक्रम, प्रारंभ करें, कंसोल संलग्न और जारी करने ConsoleCtrlEvent
  • द्वारा रोक

संपादित करें: जो लोग यहाँ कोड में रुचि रखते हैं के लिए KindDragon पर संशोधित समाधान और अभी व। यदि आप पहले को रोकने के बाद अन्य प्रोग्राम शुरू करने की योजना बना रहे हैं, तो आपको Ctrl-C हैंडलिंग को फिर से सक्षम करना चाहिए, अन्यथा अगली प्रक्रिया माता-पिता की अक्षम स्थिति का वारिस करेगी और Ctrl-C का जवाब नहीं देगी।

[DllImport("kernel32.dll", SetLastError = true)] 
static extern bool AttachConsole(uint dwProcessId); 

[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] 
static extern bool FreeConsole(); 

// Enumerated type for the control messages sent to the handler routine 
enum CtrlTypes : uint 
{ 
    CTRL_C_EVENT = 0, 
    CTRL_BREAK_EVENT, 
    CTRL_CLOSE_EVENT, 
    CTRL_LOGOFF_EVENT = 5, 
    CTRL_SHUTDOWN_EVENT 
} 

[DllImport("kernel32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
private static extern bool GenerateConsoleCtrlEvent(CtrlTypes dwCtrlEvent, uint dwProcessGroupId); 

public void StopProgram(Process proc) 
{ 
    //This does not require the console window to be visible. 
    if (AttachConsole((uint)proc.Id)) 
    { 
    // Disable Ctrl-C handling for our program 
    SetConsoleCtrlHandler(null, true); 
    GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, 0); 

    // Must wait here. If we don't and re-enable Ctrl-C 
    // handling below too fast, we might terminate ourselves. 
    proc.WaitForExit(2000); 

    FreeConsole(); 

    //Re-enable Ctrl-C handling or any subsequently started 
    //programs will inherit the disabled state. 
    SetConsoleCtrlHandler(null, false); 
    } 
} 

इसके अलावा, एक आपात समाधान अगर AttachConsole() या भेजा संकेत के लिए योजना को विफल करना चाहिए, उदाहरण के तो सो के लिए इस:

if (!proc.HasExited) 
{ 
    try 
    { 
    proc.Kill(); 
    } 
    catch (InvalidOperationException e){} 
} 
+5

यह स्वीकार्य उत्तर होना चाहिए। – Triynko

+4

इससे प्रेरित, मैंने एक "स्टैंडअलोन" सीपीपी ऐप बनाया जो यह करता है: https://gist.github.com/rdp/f51fb274d69c5c31b6be यह उपयोगी होने पर। और हां, यह विधि स्पष्ट रूप से "किसी भी" पिड को ctrl + c या ctrl + ब्रेक भेज सकती है। – rogerdpack

+0

डीएलएल आयात में से एक को खोना "SetConsoleCtrlHandler", लेकिन यह काम करता है। –

1

मैं यह सब जटिल पाया और SendKeys इस्तेमाल किया एक CTRL भेजने के लिए - सी कमांड लाइन विंडो (यानी cmd.exe विंडो) के वर्कअराउंड के रूप में कीस्ट्रोक।

1

मेरा एक मित्र ने समस्या को हल करने का एक अलग अलग तरीका सुझाया और यह मेरे लिए काम किया। नीचे की तरह एक vbscript का प्रयोग करें। यह शुरू होता है और एप्लिकेशन, इसे 7 सेकंड तक चलाएं और इसे ctrl + c का उपयोग करके बंद करें।

'VBScript उदाहरण

Set WshShell = WScript.CreateObject("WScript.Shell") 

WshShell.Run "notepad.exe" 

WshShell.AppActivate "notepad" 

WScript.Sleep 7000 

WshShell.SendKeys "^C" 
+0

यह काम करता है यदि एप्लिकेशन में एक विंडो है जिसे आप AppActive (अग्रभूमि में ला सकते हैं) कर सकते हैं। – rogerdpack

2

यह क्रिस्टल स्पष्ट कर दिया जाना चाहिए क्योंकि इस समय ऐसा नहीं है। Ctrl-C भेजने के लिए SendSignal का एक संशोधित और संकलित संस्करण है (डिफ़ॉल्ट रूप से यह केवल Ctrl + Break भेजता है)। यहाँ कुछ बाइनरी हैं:

(2014-3-7): मैं Ctrl-C के साथ 32-बिट और 64-बिट संस्करण का निर्माण किया है, यह SendSignalCtrlC.exe कहा जाता है और आप इसे डाउनलोड कर सकते हैं: https://dl.dropboxusercontent.com/u/49065779/sendsignalctrlc/x86/SendSignalCtrlC.exehttps://dl.dropboxusercontent.com/u/49065779/sendsignalctrlc/x86_64/SendSignalCtrlC.exe - - जुराज Michalak

मैं भी सिर्फ मामले में उन फ़ाइलों को नजर आता है:
32-बिट संस्करण: https://www.dropbox.com/s/r96jxglhkm4sjz2/SendSignalCtrlC.exe?dl=0
64-बिट संस्करण: https://www.dropbox.com/s/hhe0io7mcgcle1c/SendSignalCtrlC64.exe?dl=0

अस्वीकरण: मैं का निर्माण नहीं किया उन फ़ाइल रों। संकलित मूल फ़ाइलों में कोई संशोधन नहीं किया गया था। परीक्षण का एकमात्र मंच 64-बिट विंडोज 7 है। http://www.latenighthacking.com/projects/2003/sendSignal/ पर उपलब्ध स्रोत को अनुकूलित करने और इसे स्वयं संकलित करने की अनुशंसा की जाती है।

2

यहां कोड है जो मैं अपने सी ++ ऐप में उपयोग करता हूं।

सकारात्मक अंक: सांत्वना app से

  • वर्क्स
  • Windows सेवा
  • कोई देरी आवश्यक
  • वर्तमान एप्लिकेशन

नकारात्मक अंक बंद नहीं करता है से

  • वर्क्स :

    • मुख्य सांत्वना खो दिया है और एक नया (FreeConsole देखें)
    • सांत्वना स्विचिंग अजीब परिणाम दे बनाई गई है ...

    // Inspired from http://stackoverflow.com/a/15281070/1529139 
    // and http://stackoverflow.com/q/40059902/1529139 
    bool signalCtrl(DWORD dwProcessId, DWORD dwCtrlEvent) 
    { 
        bool success = false; 
        DWORD thisConsoleId = GetCurrentProcessId(); 
        // Leave current console if it exists 
        // (otherwise AttachConsole will return ERROR_ACCESS_DENIED) 
        bool consoleDetached = (FreeConsole() != FALSE); 
    
        if (AttachConsole(dwProcessId) != FALSE) 
        { 
         // Add a fake Ctrl-C handler for avoid instant kill is this console 
         // WARNING: do not revert it or current program will be also killed 
         SetConsoleCtrlHandler(nullptr, true); 
         success = (GenerateConsoleCtrlEvent(dwCtrlEvent, 0) != FALSE); 
         FreeConsole(); 
        } 
    
        if (consoleDetached) 
        { 
         // Create a new console if previous was deleted by OS 
         if (AttachConsole(thisConsoleId) == FALSE) 
         { 
          int errorCode = GetLastError(); 
          if (errorCode == 31) // 31=ERROR_GEN_FAILURE 
          { 
           AllocConsole(); 
          } 
         } 
        } 
        return success; 
    } 
    

    प्रयोग उदाहरण:

    DWORD dwProcessId = ...; 
    if (signalCtrl(dwProcessId, CTRL_C_EVENT)) 
    { 
        cout << "Signal sent" << endl; 
    } 
    
  • 1

    प्रक्रिया आईडी के आधार पर, हम बलपूर्वक या कृपापूर्वक या किसी अन्य सिग्नल को समाप्त करने के लिए प्रक्रिया को सिग्नल भेज सकते हैं।

    सूची सभी प्रक्रिया:

    C:\>Taskkill /IM firefox.exe /F 
    or 
    C:\>Taskkill /PID 26356 /F 
    

    विवरण::

    C:\>tasklist 
    

    प्रक्रिया को मारने के लिए

    http://tweaks.com/windows/39559/kill-processes-from-command-prompt/

    2

    जावा में, Kernel32.dll पुस्तकालय के साथ JNA का उपयोग कर, एक सी ++ समाधान के समान। CtrlCSender मुख्य विधि को एक प्रक्रिया के रूप में चलाता है जो केवल Ctrl + C ईवेंट भेजने और ईवेंट उत्पन्न करने के लिए प्रक्रिया का कंसोल प्राप्त करता है। चूंकि यह कंसोल के बिना अलग-अलग चलता है तो Ctrl + C ईवेंट को अक्षम करने और फिर सक्षम करने की आवश्यकता नहीं होती है।

    CtrlCSender.java - Nemo1024's और KindDragon's उत्तरों के आधार पर।

    ज्ञात प्रक्रिया आईडी को देखते हुए, यह असंगत एप्लिकेशन लक्षित प्रक्रिया के कंसोल को संलग्न करेगा और उस पर CTRL + C ईवेंट उत्पन्न करेगा।

    import com.sun.jna.platform.win32.Kernel32;  
    
    public class CtrlCSender { 
    
        public static void main(String args[]) { 
         int processId = Integer.parseInt(args[0]); 
         Kernel32.INSTANCE.AttachConsole(processId); 
         Kernel32.INSTANCE.GenerateConsoleCtrlEvent(Kernel32.CTRL_C_EVENT, 0); 
        } 
    } 
    

    मुख्य आवेदन - एक अलग consoless प्रक्रिया

    ProcessBuilder pb = new ProcessBuilder(); 
    pb.command("javaw", "-cp", System.getProperty("java.class.path", "."), CtrlCSender.class.getName(), processId); 
    pb.redirectErrorStream(); 
    pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); 
    pb.redirectError(ProcessBuilder.Redirect.INHERIT); 
    Process ctrlCProcess = pb.start(); 
    ctrlCProcess.waitFor(); 
    
    1
     void SendSIGINT(HANDLE hProcess) 
         { 
          DWORD pid = GetProcessId(hProcess); 
          FreeConsole(); 
          if (AttachConsole(pid)) 
          { 
           // Disable Ctrl-C handling for our program 
           SetConsoleCtrlHandler(NULL, true); 
    
           GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); // SIGINT 
    
           //Re-enable Ctrl-C handling or any subsequently started 
           //programs will inherit the disabled state. 
           SetConsoleCtrlHandler(NULL, false); 
    
           WaitForSingleObject(hProcess, 10000); 
          } 
         } 
    
    संबंधित मुद्दे