简体   繁体   English

Win32应用程序使用printf将输出写入控制台

[英]Win32 application write output to console using printf

I have an exe developed using win32 application. 我有一个使用win32应用程序开发的exe。 When I run (double click) the exe GUI should appear and when i call exe from command prompt output should appear in command console. 当我运行(双击)时,应该会出现exe GUI,并且当我从命令提示符输出调用exe时,应该会出现在命令控制台中。

My issue is how can i redirect output to command window using printf ? 我的问题是如何使用printf将输出重定向到命令窗口? I am able to print in command window using AllocConsole() , but new command window is created and output is redirected to new window. 我可以使用AllocConsole()在命令窗口中进行打印,但是会创建新的命令窗口,并将输出重定向到新窗口。 I want to print output in same command window where exe is called using Win32 application. 我想在使用Win32应用程序调用exe的同一命令窗口中打印输出。 Any help appreciated. 任何帮助表示赞赏。

To build on what wilx said (sorry I don't have enough reputation to just comment on his answer) you can use AttachConsole(...); 要基于wilx所说的(抱歉,我没有足够的声誉就只能对他的回答发表评论),可以使用AttachConsole(...); So to attach to a console if an only if there is already one available you could use something like: 因此,如果仅在已经有一个可用控制台的情况下将其附加到控制台,则可以使用以下命令:

bool bAttachToConsole()
{
    if (!AttachConsole(ATTACH_PARENT_PROCESS))
    {
        if (GetLastError() != ERROR_ACCESS_DENIED) //already has a console
        {
            if (!AttachConsole(GetCurrentProcessId()))
            {
                DWORD dwLastError = GetLastError();
                if (dwLastError != ERROR_ACCESS_DENIED) //already has a console
                {
                    return false;
                }
            }
        }
    }

    return true;
}

Then in your WinMain you can do this: 然后在您的WinMain中,您可以执行以下操作:

if (bAttachToConsole())
{
    //do your io with STDIN/STDOUT
    // ....
}
else
{
    //Create your window and do IO via your window
    // ....
}

Additionally you will have to "fix" the c standard IO handles to use your new console see the following write up for a great example of how to do this. 此外,您将有“修复” C标准IO处理,以使用新的控制台中看到下面写了关于如何做一个很好的例子。

This almost does what you want: 这几乎可以满足您的要求:

// Win32Project1.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include <stdio.h>  // printf, _dup2
#include <io.h>     // _open_osfhandle

void SetupConsole()
{
    AttachConsole(ATTACH_PARENT_PROCESS);
    HANDLE hConIn = GetStdHandle(STD_INPUT_HANDLE);
    int fd0 = _open_osfhandle((intptr_t)hConIn, 0);
    _dup2(fd0, 0);
    HANDLE hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
    int fd1 = _open_osfhandle((intptr_t)hConOut, 0);
    _dup2(fd1, 1);
    HANDLE hConErr = GetStdHandle(STD_ERROR_HANDLE);
    int fd2 = _open_osfhandle((intptr_t)hConErr, 0);
    _dup2(fd2, 2);
}

WNDPROC g_pOldProc;

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if (uMsg == WM_CLOSE)
    {
        PostQuitMessage(0);
        return 0;
    }

    return CallWindowProc(g_pOldProc, hwnd, uMsg, wParam, lParam);
}

void GUI(HINSTANCE hInstance)
{
    HWND hWnd = CreateWindow(
                        _T("EDIT"),
                        _T("GUI"),
                        WS_OVERLAPPEDWINDOW|WS_VISIBLE,
                        100, 100, 200,200,
                        NULL,
                        NULL,
                        hInstance,
                        NULL
                        );
    g_pOldProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)&WindowProc);

    SetWindowText(hWnd, _T("Hello world."));

    MSG m;
    while (GetMessage(&m, NULL, 0, 0))
    {
        DispatchMessage(&m);
    }

    DestroyWindow(hWnd);
}

void Console()
{
    SetupConsole();
    printf("Hello world.");
}

int APIENTRY _tWinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPTSTR    lpCmdLine,
                       int       nCmdShow)
{
    HANDLE hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (!hConOut)
        GUI(hInstance);
    else
        Console();

    return 0;
}

Try using AttachConsole(ATTACH_PARENT_PROCESS) (or use PID) to attach to the existing console. 尝试使用AttachConsole(ATTACH_PARENT_PROCESS) (或使用PID)来附加到现有控制台。


While I have posted my answer already, TBH, I am not sure I do understand your problem exactly. 虽然我已经发布了答案,TBH,但是我不确定我是否确实了解您的问题。 I have some code that has a comment that says (above AllocConsole() : 我有一些代码带有注释(在AllocConsole()上方:

We ignore the return value here. 我们在这里忽略返回值。 If we already have a console, it will fail. 如果我们已经有了一个控制台,它将失败。

Are you sure that you cannot just use AllocConsole() unconditionally like I do? 您确定不能像我一样无条件地使用AllocConsole()吗?

Try this: 尝试这个:

// Win32Project1.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include <stdio.h>  // printf
#include <io.h>     // _open_osfhandle, _dup2

void SetupConsole()
{
    BOOL bCreated = AllocConsole();
    if (!bCreated)
        return; // We already have a console.

    HANDLE hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
    int fd = _open_osfhandle((intptr_t)hConOut, 0);
    _dup2(fd, 1);

}

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    SetupConsole();
    printf("Hello world!");
    Sleep(10000);

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM