Win32

2013-08-17 3 views
9

पर संभाल CTRL + C मैं CTRL + सी घटनाओं से निपटने के साथ कुछ समस्याएं एक Win32 सी ++ सांत्वना कार्यक्रम में, है।Win32

असल में मेरा कार्यक्रम इस प्रकार है: (यह अन्य प्रश्न के आधार पर: Windows Ctrl-C - Cleaning up local stack objects in command line app)

bool running; 

int main() { 

    running = true; 
    SetConsoleCtrlHandler((PHANDLER_ROUTINE) consoleHandler, TRUE); 

    while (running) { 
     // do work 
     ... 
    } 

    // do cleanup 
    ... 

    return 0; 
} 

bool consoleHandler(int signal) { 

    if (signal == CTRL_C_EVENT) { 

     running = false; 
    } 
    return true; 
} 

समस्या नहीं निष्पादित किया जा रहा सफाई कोड है।

हैंडलर फ़ंक्शन के निष्पादन के बाद प्रक्रिया समाप्त हो जाती है, लेकिन मुख्य लूप के बाद कोड निष्पादित किए बिना। क्या गलत है?

संपादित करें: के रूप में अनुरोध, यह एक कम से कम परीक्षण का मामला मेरे कार्यक्रम के समान है: http://pastebin.com/6rLK6BU2

मैं "परीक्षण सफाई-अनुदेश" मेरे उत्पादन में स्ट्रिंग नहीं मिलता है।

मुझे नहीं पता कि यह महत्वपूर्ण है, मैं MinGW के साथ संकलित कर रहा हूं।


संपादित करें 2: परीक्षण का मामला कार्यक्रम के साथ समस्या यह Sleep() समारोह का उपयोग है। इसके बिना कार्यक्रम अपेक्षित काम करता है।

Win32 में फ़ंक्शन हैंडलर किसी अन्य थ्रेड में चलता है, इसलिए जब हैंडलर/थ्रेड इसके निष्पादन को समाप्त करता है तो मुख्य धागा सो रहा है। शायद यह प्रक्रिया बाधा का कारण है?

+3

'SetConsoleCtrlHandler' वापस क्या करता है? – Caesar

+0

SetConsoleCtrlHandler का वापसी मूल्य क्या है? आप त्रुटियों के लिए यह जांच नहीं रहे हैं, btw – lpapp

+1

क्या आप सुनिश्चित हैं कि 'कंसोल हैंडलर' फ़ंक्शन बिल्कुल चलता है? यदि आप डीबगर में प्रोग्राम चलाते हैं और इसमें ब्रेकपॉइंट सेट करते हैं, तो क्या यह ब्रेकपॉइंट पर रुक जाएगा? –

उत्तर

7

निम्नलिखित कोड मेरे लिए काम करता है:

#include <windows.h> 
#include <stdio.h> 

BOOL WINAPI consoleHandler(DWORD signal) { 

    if (signal == CTRL_C_EVENT) 
     printf("Ctrl-C handled\n"); // do cleanup 

    return TRUE; 
} 

int main() 
{ 
    running = TRUE; 
    if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) { 
     printf("\nERROR: Could not set control handler"); 
     return 1; 
    } 

    while (1) { /* do work */ } 

    return 0; 
} 
10

the documentation, जब हैंडलर (जो गलत घोषित किया जाता है, BTW) एक CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, या CTRL_SHUTDOWN_EVENT संकेत प्राप्त के अनुसार, प्रक्रिया हैंडलर के बाद समाप्त हो जाता है बाहर निकलता है। आप जो भी प्रयास कर रहे हैं, उसे करने के लिए, आपको अपने क्लीनअप कोड को हैंडलर में ही ले जाना चाहिए।

+0

ऐसा लगता है कि मेरा प्रोग्राम इन घटनाओं को प्राप्त नहीं कर रहा है, लेकिन केवल एक 'CTRL_C_EVENT' है। मेरे हैंडलर फ़ंक्शन में 'स्विच' के साथ अभी परीक्षण किया गया है, और कंसोल से CTRL + C को मार रहा है। – eang

8

आपकी विशिष्ट आवश्यकताओं के आधार पर आपके पास कई विकल्प हैं। आप बस Ctrl +सी अनदेखी करने के लिए चाहते हैं तो आप HandlerRoutine पैरामीटर के रूप में NULL गुजर SetConsoleCtrlHandler कॉल कर सकते हैं:

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    SetConsoleCtrlHandler(NULL, TRUE); 

    // do work 

    return 0; 
} 

यह सब संकेत संचालकों को हटा। इस एप्लिकेशन को समाप्त करने के लिए आपको बंद करने के लिए निर्धारित करने के लिए कस्टम तर्क लागू करना होगा।

आप Ctrl +सी को संभालने के लिए चाहते हैं तो आप दो विकल्प हैं: संकेत के लिए कोई हैंडलर सेट करें या नियमित कीबोर्ड से निपटने के लिए पर कीबोर्ड इनपुट गुजरती हैं।

एक हैंडलर सेट करना ऊपर दिए गए कोड के समान है, लेकिन NULL को हैंडलर के रूप में पास करने के बजाय आप अपना स्वयं का कार्यान्वयन प्रदान करते हैं।

#include <windows.h> 
#include <stdio.h> 

volatile bool isRunnung = true; 

BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType) { 
    switch (dwCtrlType) 
    { 
    case CTRL_C_EVENT: 
     printf("[Ctrl]+C\n"); 
     isRunnung = false; 
     // Signal is handled - don't pass it on to the next handler 
     return TRUE; 
    default: 
     // Pass signal on to the next handler 
     return FALSE; 
    } 
} 


int _tmain(int argc, _TCHAR* argv[]) 
{ 
    SetConsoleCtrlHandler(HandlerRoutine, TRUE); 

    printf("Starting\n"); 
    while (isRunnung) { 
     Sleep(0); 
    } 
    printf("Ending\n"); 

    return 0; 
} 

इस आवेदन के उत्पादन में है:

Starting 
[Ctrl]+C 
Ending 

ध्यान दें कि सफाई कोड निष्पादित होने पर, कोड की परवाह किए बिना मुख्य while -loop अंदर। सिग्नल हैंडलर एक लिंक्ड सूची बनाते हैं, जहां हैंडलर फ़ंक्शन को अंतिम-पंजीकृत, पहले-कॉल किए गए आधार पर कॉल किया जाता है जब तक कि हैंडलर में से कोई एक TRUE लौटाता है। यदि कोई भी हैंडलर सत्य नहीं लौटाता है, तो डिफ़ॉल्ट हैंडलर को बुलाया जाता है। प्रसंस्करण करते समय कंसोल के लिए डिफ़ॉल्ट हैंडलर ExitProcess पर कॉल करता है Ctrl + सी

आप किसी भी पूर्व प्रसंस्करण रोकने के लिए और संभाल नियमित कीबोर्ड इनपुट के रूप में Ctrl +सी चाहते हैं बजाय आप SetConsoleMode फोन करके कंसोल मोड बदलना होगा।

#include <windows.h> 
#include <stdio.h> 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    DWORD dwMode = 0x0; 
    GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &dwMode); 
    // Remove ENABLE_PROCESSED_INPUT flag 
    dwMode &= ~ENABLE_PROCESSED_INPUT; 
    SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), dwMode); 

    while (true) { 
     // Ctrl+C can be read using ReadConsoleInput, etc. 
    } 

    return 0; 
} 

एक बार ENABLE_PROCESSED_INPUT झंडा हटा दिया जाता है Ctrl +सी नहीं रह गया है प्रणाली द्वारा संसाधित और नियमित रूप से कुंजीपटल इनपुट की तरह कंसोल के लिए पारित कर दिया है। इसे ReadConsoleInput या ReadFile का उपयोग करके पढ़ा जा सकता है।

अस्वीकरण: उपर्युक्त 32 और 64 बिट, रिलीज और डीबग कॉन्फ़िगरेशन के लिए संकलित विंडोज 8 64 बिट पर परीक्षण किया गया है।