मैं Win32 ऐप में डिबग आउटपुट विंडो पर कैसे प्रिंट करूं?


97

मुझे एक win32 प्रोजेक्ट मिला है जिसे मैंने Visual Studio 2005 में लोड किया है। मैं विज़ुअल स्टूडियो आउटपुट विंडो में चीजों को प्रिंट करने में सक्षम होना चाहता हूं, लेकिन मैं अपने जीवन के लिए काम नहीं कर सकता। मैंने 'printf' और 'cout <<' आज़माया है, लेकिन मेरे संदेश ज़बर्दस्त रूप से अप्रकाशित रहते हैं।

क्या विजुअल स्टूडियो आउटपुट विंडो में प्रिंट करने के लिए कुछ विशेष तरीके हैं?


11
ध्यान दें कि Visual Studio आउटपुट विंडो कंसोल नहीं है। वे दोनों "उन में पाठ के साथ खिड़कियां" हैं, लेकिन पर्दे के पीछे अलग हैं।
एमएसलेटर 9

जवाबों:


136

आप उपयोग कर सकते हैं OutputDebugStringOutputDebugStringएक मैक्रो है जो आपके बिल्ड विकल्पों के आधार पर या तो मैप करता है OutputDebugStringA(char const*)या OutputDebugStringW(wchar_t const*)। बाद के मामले में आपको फ़ंक्शन को एक विस्तृत वर्ण स्ट्रिंग प्रदान करना होगा। एक विस्तृत वर्ण शाब्दिक बनाने के लिए आप Lउपसर्ग का उपयोग कर सकते हैं :

OutputDebugStringW(L"My output string.");

आम तौर पर आप मैक्रो संस्करण का उपयोग मैक्रो के साथ _Tइस तरह करेंगे:

OutputDebugString(_T("My output string."));

यदि आप परियोजना को UNICODE के लिए बनाने के लिए कॉन्फ़िगर किया गया है, तो इसमें विस्तार होगा:

OutputDebugStringW(L"My output string.");

यदि आप UNICODE के लिए निर्माण नहीं कर रहे हैं, तो इसमें विस्तार होगा:

OutputDebugStringA("My output string.");

2
उत्तम! धन्यवाद। पूर्णता के लिए हालांकि, यह पता चला कि मुझे ऐसा करना था: आउटपुटडबगस्ट्रिंग (पाठ ("हैलो कंसोल वर्ल्ड")); .. शायद किसी तरह के यूनिकोड से संबंधित निर्माण विकल्प के कारण।
izb

1
ध्यान दें कि आप sysinternals से डीबग्यूव करने के लिए उपयोगी पाएंगे। यह आपको ओडीएस आउटपुट देखने की अनुमति देता है भले ही विजुअल स्टूडियो बॉक्स पर नहीं चल रहा हो (या स्थापित भी हो)
pm100

4
@CDT: यह के प्रकार पर निर्भर करता है myStr। यह है char*, wchar_t*या LPTSTR? मान लिया जाये कि यह है कि char*आप बस फोन OutputDebugStringA(myStr)या उपयोग OutputDebugStringWके साथ wchar_t*और OutputDebugStringसाथ LPTSTRके रूप में मेरा उत्तर में विस्तार से बताया।
मार्टिन लीवरेज

1
@CDT: किसी एकल पैरामीटर वाले फ़ंक्शन को कॉल करने की तुलना में सरल क्या है जो वह संदेश है जिसे आप आउटपुट करना चाहते हैं? क्या यह ANSI / UNICODE जटिलता है? बस उपयोग करें OutputDebugStringऔर या तो उपयुक्त प्रीप्रोसेसर प्रतीकों को परिभाषित करें जो आपके द्वारा उपयोग किए जाने वाले पात्रों की चौड़ाई से मेल खाते हैं या लचीले "टी" प्रकारों के साथ चलते हैं जो आपको 8 और 16 बिट पात्रों दोनों को संकलित करने की अनुमति देता है।
मार्टिन लीवरेज

1
@ मोनाजलाल: आपकी टिप्पणी से यह स्पष्ट नहीं है कि कौन सी स्क्रीन है इसलिए आपको विशिष्ट सलाह देना थोड़ा कठिन है। यदि आप अपनी प्रक्रिया को डीबग करते हैं तो डीबगर आउटपुट डिबग प्रदर्शित करने का एक तरीका होगा। यदि आप अपने डिबगर के रूप में विजुअल स्टूडियो का उपयोग कर रहे हैं तो आउटपुट आउटपुट विंडो में दिखाया गया है । वास्तव में उत्पादन आप का चयन करने के लिए है यह देखने के लिए डीबग से से उत्पादन शो लटकती। यदि आप किसी कारण से किसी डिबगर के बाहर अपनी प्रक्रिया चला रहे हैं, तो आप सभी प्रक्रियाओं से डीबग आउटपुट देखने के लिए DebugView का उपयोग कर सकते हैं ।
मार्टिन लिवरेज

29

यदि प्रोजेक्ट GUI प्रोजेक्ट है, तो कोई कंसोल दिखाई नहीं देगा। प्रोजेक्ट को कंसोल में बदलने के लिए आपको प्रोजेक्ट प्रॉपर्टीज पैनल में जाकर सेट करना होगा:

  • " लिंकर-> सिस्टम-> सबसिस्टम " में मान " कंसोल (/ SUBSYSTEM: CONSOLOL ) "
  • " C / C ++ -> Preprocessor-> Preprocessor परिभाषाएँ " में " _CONSOLE " परिभाषित करें

यह समाधान केवल तभी काम करता है जब आपके पास क्लासिक " int main () " एंट्री पॉइंट था।

लेकिन अगर आप मेरे मामले में हैं (एक ओपन प्रोजेक्ट), तो आपको संपत्तियों को संपादित करने की आवश्यकता नहीं है, क्योंकि यह बेहतर काम करता है:

AllocConsole();
freopen("CONIN$", "r",stdin);
freopen("CONOUT$", "w",stdout);
freopen("CONOUT$", "w",stderr);

प्रिंटफ और कॉउट हमेशा की तरह काम करेंगे।

यदि आप विंडो के निर्माण से पहले AllocConsole कहते हैं, तो कंसोल विंडो के पीछे दिखाई देगा, यदि आप इसे कॉल करते हैं, तो यह आगे दिखाई देगा।

अपडेट करें

freopenवंचित है और असुरक्षित हो सकता है। freopen_sइसके बजाय उपयोग करें :

FILE* fp;

AllocConsole();
freopen_s(&fp, "CONIN$", "r", stdin);
freopen_s(&fp, "CONOUT$", "w", stdout);
freopen_s(&fp, "CONOUT$", "w", stderr);

EDITBINCONSOLEयदि आप इसके WinMainबजाय उपयोग कर रहे हैं तो भी सबसिस्टम सेट कर सकते हैं int main()
बेन वोइग्ट

1
@Zac। धन्यवाद! AllocConsole () के साथ शुरू होने वाली 4 लाइनों ने बहुत अच्छा काम किया। इसके लिए प्लस 1। और कुछ भी काम नहीं कर रहा था, हालाँकि मुझे Win32 परियोजनाओं में / SUBSYSTEM: CONSOLE और / या _CONSOLE मैक्रोज़ का उपयोग करने से पहले दिखाने के लिए कंसोल मिला है। पता नहीं क्यों मैक्रों ने आज शाम काम नहीं किया। क्या कॉमन लैंग्वेज रनटाइम सपोर्ट (/ clr) का उपयोग करने से इसका कोई लेना-देना हो सकता है ?
राइडरबिल

12

realकंसोल पर प्रिंट करने के लिए , आपको लिंकर ध्वज का उपयोग करके इसे दिखाई देने की आवश्यकता है /SUBSYSTEM:CONSOLE। अतिरिक्त कंसोल विंडो कष्टप्रद है, लेकिन डीबगिंग उद्देश्यों के लिए यह बहुत मूल्यवान है।

OutputDebugString डीबगर के अंदर चलने पर डीबगर आउटपुट पर प्रिंट करता है।


6
आप AllocConsole ()
बिली

4

_RPT N () और _RPTF N () रिपोर्टिंग के लिए VC ++ रनटाइम मैक्रोज़ का उपयोग करने पर विचार करें।

डिबगिंग के लिए प्रिंटफ स्टेटमेंट के उपयोग को बदलने के लिए आप CRTDBG.H में परिभाषित _RPTn, और _RPTFn मैक्रोज़ का उपयोग कर सकते हैं। ये मैक्रो स्वचालित रूप से आपकी रिलीज़ बिल्ड में गायब हो जाते हैं जब _DEBUG परिभाषित नहीं होता है, इसलिए उन्हें #ifffs में संलग्न करने की कोई आवश्यकता नहीं है।

उदाहरण...

if (someVar > MAX_SOMEVAR) {
    _RPTF2(_CRT_WARN, "In NameOfThisFunc( )," 
         " someVar= %d, otherVar= %d\n", someVar, otherVar );
}

या आप सीधे VC ++ रनटाइम फ़ंक्शंस _CrtDbgReport, _CrtDbgReportW का उपयोग कर सकते हैं ।

_CrtDbgReport और _CrtDbgReportW डिबग रिपोर्ट को तीन अलग-अलग गंतव्यों पर भेज सकते हैं: एक डीबग रिपोर्ट फ़ाइल, एक डीबग मॉनिटर (विज़ुअल स्टूडियो डीबगर), या डीबग संदेश विंडो।

_CrtDbgReport और _CrtDbgReportW, स्वरूप स्ट्रिंग में तर्क [n] तर्कों को प्रिंट या wff फ़ंक्शन द्वारा परिभाषित समान नियमों का उपयोग करके डिबग रिपोर्ट के लिए उपयोगकर्ता संदेश बनाते हैं। ये फ़ंक्शन तब डिबग रिपोर्ट उत्पन्न करते हैं और गंतव्य या गंतव्यों को निर्धारित करते हैं, जो वर्तमान रिपोर्ट मोड और रिपोर्टटाइप के लिए परिभाषित फ़ाइल के आधार पर निर्धारित करते हैं। जब रिपोर्ट डीबग संदेश विंडो में भेजी जाती है, तो फ़ाइलनाम, लाइननंबर और मॉड्यूलनाम विंडो में प्रदर्शित जानकारी में शामिल होते हैं।


यह जवाब देने या जोड़ने के लायक _RPTF0है जिसका उपयोग किया जा सकता है जहां प्रारूप स्ट्रिंग के बाद कोई भी चर पास होने की उम्मीद नहीं है। _RPTFNमैक्रो, दूसरे हाथ पर, की आवश्यकता है प्रारूप स्ट्रिंग निम्नलिखित कम से कम एक तर्क।
एमएन

4

यदि आप दशमलव चर प्रिंट करना चाहते हैं:

wchar_t text_buffer[20] = { 0 }; //temporary buffer
swprintf(text_buffer, _countof(text_buffer), L"%d", your.variable); // convert
OutputDebugString(text_buffer); // print

4

यदि आपको किसी मौजूदा प्रोग्राम के आउटपुट को देखने की आवश्यकता है जो बड़े पैमाने पर प्रिंट डब्ल्यू / ओ का उपयोग कोड को बदल रहा है (या न्यूनतम बदलाव के साथ) तो आप प्रिंटफ को निम्नानुसार फिर से परिभाषित कर सकते हैं और इसे सामान्य हेडर (stdafx.h) में जोड़ सकते हैं।

int print_log(const char* format, ...)
{
    static char s_printf_buf[1024];
    va_list args;
    va_start(args, format);
    _vsnprintf(s_printf_buf, sizeof(s_printf_buf), format, args);
    va_end(args);
    OutputDebugStringA(s_printf_buf);
    return 0;
}

#define printf(format, ...) \
        print_log(format, __VA_ARGS__)

1
स्थिर बफ़र की वजह से सावधान रहें, यह फ़ंक्शन रीएन्ट्रेंट नहीं है और विभिन्न थ्रेड्स से उपयोग नहीं किया जा सकता है।
निकाज़ो

2

आपका Win32 प्रोजेक्ट एक GUI प्रोजेक्ट है, कंसोल प्रोजेक्ट नहीं। यह निष्पादन योग्य हेडर में अंतर का कारण बनता है। परिणामस्वरूप, आपका GUI प्रोजेक्ट स्वयं की विंडो खोलने के लिए जिम्मेदार होगा। हालांकि यह एक कंसोल विंडो हो सकती है। AllocConsole()इसे बनाने के लिए कॉल करें, और इसे लिखने के लिए Win32 कंसोल फ़ंक्शन का उपयोग करें।


2

मैं अपने आप को ऐसा करने के लिए एक रास्ता खोज रहा था और एक सरल समाधान का पता लगा रहा था।

मैं मान रहा हूं कि आपने Visual Studio में एक डिफ़ॉल्ट Win32 प्रोजेक्ट (Windows अनुप्रयोग) शुरू किया है, जो "WinMain" फ़ंक्शन प्रदान करता है। डिफ़ॉल्ट रूप से, विज़ुअल स्टूडियो "SUBSYSTEM: WINDOWS" के लिए प्रवेश बिंदु निर्धारित करता है। आपको पहले इसे बदलने की आवश्यकता है:

प्रोजेक्ट -> गुण -> लिंकर -> सिस्टम -> सबसिस्टम

और ड्रॉप-डाउन सूची से "कंसोल (/ SUBSYSTEM: CONSOLE)" चुनें।

अब, प्रोग्राम नहीं चलेगा, क्योंकि "WinMain" फ़ंक्शन के बजाय "मुख्य" फ़ंक्शन की आवश्यकता है।

तो अब आप "मुख्य" फ़ंक्शन को जोड़ सकते हैं जैसे आप सामान्य रूप से C ++ में करेंगे। इसके बाद, GUI कार्यक्रम शुरू करने के लिए, आप "WinMain" फ़ंक्शन को "मुख्य" फ़ंक्शन के अंदर से कॉल कर सकते हैं।

आपके कार्यक्रम का शुरुआती हिस्सा अब कुछ इस तरह दिखना चाहिए:

#include <iostream>

using namespace std;

// Main function for the console
int main(){

    // Calling the wWinMain function to start the GUI program
    // Parameters:
    // GetModuleHandle(NULL) - To get a handle to the current instance
    // NULL - Previous instance is not needed
    // NULL - Command line parameters are not needed
    // 1 - To show the window normally
    wWinMain(GetModuleHandle(NULL), NULL,NULL, 1); 

    system("pause");
    return 0;
}

// Function for entry into GUI program
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    // This will display "Hello World" in the console as soon as the GUI begins.
    cout << "Hello World" << endl;
.
.
.

मेरे कार्यान्वयन का परिणाम

अब आप डिबगिंग या अन्य उद्देश्यों के लिए अपने GUI प्रोग्राम के किसी भी भाग में कंसोल के आउटपुट के लिए फ़ंक्शन का उपयोग कर सकते हैं।


2

कंसोल पर मुद्रित करने के लिए आप WriteConsole विधि का उपयोग भी कर सकते हैं ।

AllocConsole();
LPSTR lpBuff = "Hello Win32 API";
DWORD dwSize = 0;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), lpBuff, lstrlen(lpBuff), &dwSize, NULL);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.