Win32 uygulamasında hata ayıklama çıktı penceresine nasıl yazdırırım?


99

Visual Studio 2005'e yüklediğim bir win32 projem var. İşleri Visual Studio çıktı penceresine yazdırabilmek istiyorum, ancak hayatım boyunca nasıl çalıştığımı çözemiyorum. 'Printf' ve 'cout <<' denedim ama mesajlarım inatla basılmıyor.

Visual Studio çıktı penceresine yazdırmanın özel bir yolu var mı?


11
Visual Studio çıktı Penceresinin konsol olmadığını unutmayın. Her ikisi de "içinde metin olan pencerelerdir", ancak perde arkasında farklıdırlar.
MSalters

VS çıktı penceresi varsayılan olarak her iletiden önce kaynak cpp'nin tam yolunu gösteriyorsa, __ FILE __ için geçici çözümü göz önünde bulundurun .
Laurie Stearn

Yanıtlar:


138

Kullanabilirsiniz OutputDebugString. OutputDebugString, oluşturma seçeneklerinize bağlı olarak OutputDebugStringA(char const*)veya ile eşleşen bir makrodur OutputDebugStringW(wchar_t const*). Daha sonraki durumda, işleve geniş karakterli bir dizi sağlamanız gerekecektir. Geniş karakterli bir değişmez oluşturmak için Löneki kullanabilirsiniz :

OutputDebugStringW(L"My output string.");

Normalde makro versiyonunu makro ile birlikte şu şekilde kullanacaksınız _T:

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

Projeniz UNICODE için derlenecek şekilde yapılandırıldıysa, aşağıdakilere genişleyecektir:

OutputDebugStringW(L"My output string.");

UNICODE için geliştirme yapmıyorsanız, aşağıdakilere genişleyecektir:

OutputDebugStringA("My output string.");

2
Mükemmel! Teşekkürler. Yine de tamlık için şunu yapmam gerektiği ortaya çıktı: OutputDebugString (TEXT ("Merhaba konsol dünyası")); .. muhtemelen bir tür unicode ile ilgili inşa seçeneği nedeniyle.
izb

1
sysinternals'dan hata ayıklama görünümüne sahip olmanın yararlı olacağını unutmayın. Bu, Visual Studio kutuda çalışmıyor (veya hatta yüklü) olsa bile ODS çıkışını görmenizi sağlar
pm100

4
@CDT: Türüne bağlıdır myStr. Öyle mi char*, wchar_t*yoksa LPTSTR? Cevabımda açıklandığı gibi char*sadece arayın OutputDebugStringA(myStr)ya da OutputDebugStringWbirlikte wchar_t*ve OutputDebugStringile kullanın LPTSTR.
Martin Liversage

1
@CDT: Çıktısını almak istediğiniz mesaj olan tek bir parametreye sahip bir işlevi çağırmaktan daha basit olan nedir? ANSI / UNICODE karmaşıklığı mı? Sadece kullandığınız OutputDebugStringkarakterlerin genişliğine uyacak uygun önişlemci sembollerini kullanın ve tanımlayın ya da hem 8 hem de 16 bitlik karakterleri derlemenize izin veren esnek "T" tipleriyle gidin.
Martin Liversage

1
@MonaJalal: Yorumunuzdan ekranın ne olduğu net değil , bu yüzden size özel bir tavsiye vermek biraz zor. İşleminizde hata ayıklama yaparsanız, hata ayıklayıcı, hata ayıklama çıktısını görüntülemenin bir yolunu bulacaktır. Hata ayıklayıcınız olarak Visual Studio kullanıyorsanız, çıktı Çıktı penceresinde gösterilir . Aslında seçmek zorunda çıkışını görmek için Debug dan itibaren gösterin çıkışı açılır. Herhangi bir nedenle işleminizi bir hata ayıklayıcının dışında çalıştırıyorsanız , tüm işlemlerden hata ayıklama çıktısını görmek için DebugView'ı kullanabilirsiniz .
Martin Liversage

29

Proje bir GUI projesiyse, konsol görünmeyecektir. Projeyi bir konsola dönüştürmek için proje özellikleri paneline gitmeniz ve şunları ayarlamanız gerekir:

  • " Bağlayıcı-> Sistem-> Alt Sistem " de " Konsol (/ ALT SİSTEM: KONSOL) " değeri
  • " C / C ++ -> Önişlemci-> Önişlemci Tanımları " bölümünde " _CONSOLE " tanımını ekleyin

Bu çözüm yalnızca klasik " int main () " giriş noktasına sahipseniz çalışır .

Ama benim durumumdaki gibiyseniz (bir openGL projesi), daha iyi çalıştığı için özellikleri düzenlemenize gerek yoktur:

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

printf ve cout her zamanki gibi çalışacaktır.

AllocConsole'u bir pencere oluşturmadan önce ararsanız, konsol pencerenin arkasında görünecek, daha sonra ararsanız önde görünecektir.

Güncelleme

freopenkullanımdan kaldırıldı ve güvenli olmayabilir. freopen_sBunun yerine kullanın :

FILE* fp;

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

EDITBINyerine CONSOLEkullanıyor olsanız bile alt sistemi ayarlayabilirsiniz . WinMainint main()
Ben Voigt

1
@Zac. Teşekkürler! AllocConsole () ile başlayan 4 satır harika çalıştı. Bunun için artı 1. Daha önce / SUBSYSTEM: CONSOLE ve / veya _CONSOLE makrolarını kullanmadan önce Win32 projelerinde daha önce görünecek konsollar almış olmama rağmen, başka hiçbir şey çalışmıyordu. Makroların bu akşam neden çalışmadığını bilmiyorum. Ortak Dil Çalışma Zamanı Desteği (/ clr) kullanmakla bir ilgisi olabilir mi?
riderBill

12

realKonsola yazdırmak için , bağlayıcı bayrağını kullanarak onu görünür yapmanız gerekir /SUBSYSTEM:CONSOLE. Ekstra konsol penceresi can sıkıcıdır, ancak hata ayıklama amacıyla çok değerlidir.

OutputDebugString hata ayıklayıcının içinde çalışırken hata ayıklayıcı çıktısına yazdırır.


6
AllocConsole () kullanarak kendi konsolunuzu da tahsis edebilirsiniz
Billy ONeal

5

_RPT N () ve _RPTF N () Raporlamak için VC ++ çalışma zamanı Makrolarını kullanmayı düşünün

CRTDBG.H'de tanımlanan _RPTn ve _RPTFn makrolarını, hata ayıklama için printf deyimlerinin kullanımını değiştirmek için kullanabilirsiniz. Bu makrolar, _DEBUG tanımlanmadığında yayın yapınızda otomatik olarak kaybolur, bu nedenle bunları #ifdefs içine eklemenize gerek yoktur.

Misal...

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

Veya doğrudan VC ++ çalışma zamanı işlevlerini _CrtDbgReport, _CrtDbgReportW kullanabilirsiniz .

_CrtDbgReport ve _CrtDbgReportW, hata ayıklama raporunu üç farklı hedefe gönderebilir: bir hata ayıklama raporu dosyası, bir hata ayıklama izleyicisi (Visual Studio hata ayıklayıcı) veya bir hata ayıklama mesajı penceresi.

_CrtDbgReport ve _CrtDbgReportW, printf veya wprintf işlevleri tarafından tanımlanan aynı kuralları kullanarak [n] bağımsız değişkenini biçim dizesine yerleştirerek hata ayıklama raporu için kullanıcı mesajını oluşturur. Bu işlevler daha sonra hata ayıklama raporunu oluşturur ve mevcut rapor modlarına ve reportType için tanımlanan dosyaya göre hedefi veya hedefleri belirler. Rapor bir hata ayıklama mesajı penceresine gönderildiğinde, dosya adı, lineNumber ve moduleName pencerede görüntülenen bilgilere dahil edilir.


_RPTF0Biçim dizesinden sonra hiçbir değişkenin geçmesinin beklenmediği durumlarda kullanılabilecek yanıta eklemeye veya not etmeye değer . _RPTFNMakro, diğer taraftan, gerektirir biçim dizesi aşağıdaki en az bir argüman.
amn

5

Ondalık değişkenleri yazdırmak istiyorsanız:

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

%uişaretsiz için, referansa göre%f kayan nokta için .
Laurie Stearn

4

Eğer kodu değiştirmeden (veya en az değişiklikle) yoğun olarak printf kullanan mevcut bir programın çıktısını görmeniz gerekiyorsa, printf'i aşağıdaki gibi yeniden tanımlayabilir ve ortak başlığa (stdafx.h) ekleyebilirsiniz.

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
Statik tampon nedeniyle dikkatli olun, bu işlev evresel değildir ve farklı evrelerden kullanılamaz.
Nikazo

2

Win32 projeniz muhtemelen bir konsol projesi değil, bir GUI projesidir. Bu, yürütülebilir başlıkta bir farka neden olur. Sonuç olarak, GUI projeniz kendi penceresini açmaktan sorumlu olacaktır. Yine de bu bir konsol penceresi olabilir. Oluşturmak AllocConsole()için arayın ve üzerine yazmak için Win32 konsol işlevlerini kullanın.


2

Bunu kendim yapmanın bir yolunu arıyordum ve basit bir çözüm buldum.

Visual Studio'da bir "WinMain" işlevi sağlayan varsayılan bir Win32 Projesi (Windows uygulaması) başlattığınızı varsayıyorum. Varsayılan olarak, Visual Studio giriş noktasını "ALT SİSTEM: WINDOWS" olarak ayarlar. Önce bunu şu adrese giderek değiştirmeniz gerekir:

Proje -> Özellikler -> Bağlayıcı -> Sistem -> Alt Sistem

Ve açılır listeden "Konsol (/ ALT SİSTEM: KONSOL)" seçeneğini seçin.

Şimdi, "WinMain" işlevi yerine "ana" işlev gerektiğinden program çalışmayacaktır.

Yani şimdi normalde C ++ 'da olduğu gibi bir "ana" işlev ekleyebilirsiniz. Bundan sonra, GUI programını başlatmak için, "ana" işlevin içinden "WinMain" işlevini çağırabilirsiniz.

Programınızın başlangıç ​​kısmı şimdi şöyle görünmelidir:

#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;
.
.
.

Uygulamamın sonucu

Artık GUI programınızın herhangi bir bölümünde hata ayıklama veya başka amaçlarla konsola çıktı vermek için işlevleri kullanabilirsiniz.


2

Konsolda yazdırmak için WriteConsole yöntemini de kullanabilirsiniz .

AllocConsole();
LPSTR lpBuff = "Hello Win32 API";
DWORD dwSize = 0;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), lpBuff, lstrlen(lpBuff), &dwSize, NULL);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.