4

I have an exe developed using win32 application. When I run (double click) the exe GUI should appear and when i call exe from command prompt output should appear in command console.

My issue is how can i redirect output to command window using printf? I am able to print in command window using AllocConsole(), but new command window is created and output is redirected to new window. I want to print output in same command window where exe is called using Win32 application. Any help appreciated.

4
  • 3
    AttachConsole. Commented May 7, 2015 at 10:30
  • Are you asking how to act like a command line program when run from a command prompt, and run with a GUI when double clicked? Commented May 7, 2015 at 11:55
  • Not exactly a duplicate, but very closely related to stackoverflow.com/questions/24171017/… Commented May 7, 2015 at 18:45
  • There's no good way to do this. Build two executables, one GUI and one for the command line. Commented May 8, 2015 at 1:33

5 Answers 5

5

To build on what wilx said (sorry I don't have enough reputation to just comment on his answer) you can use 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:

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.

Sign up to request clarification or add additional context in comments.

2 Comments

The problem is that the command line interface won't know to wait for your program to exit, so your output will be mixed in with the command-line prompt. The problem is even worse if you need input.
Good point Harry. Starting from a console app and hiding the console via a argument maybe the only way to get the close with one exe.
2

I checked all submitted solutions here and they didn't work for me. You can always create (or change to) a CONSOLE subsystem. However, if you want to enable writing to the Console from a WIN32 appliation, not classidfied as a CONSOLE application, this code will work. After calling this function, you can just use printf (or wprintf).

My code uses AllocConsole() and then AttachConsole(), pssing to it the current process ID (obtained by calling GetProcessID).

void enableConsole()
{
    AllocConsole();
    AttachConsole(GetCurrentProcessId());
    HWND Handle = GetConsoleWindow();
    freopen("CON", "w", stdout);
}

Comments

1

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;
}

Comments

0

Try using AttachConsole(ATTACH_PARENT_PROCESS) (or use PID) to attach to the existing console.


While I have posted my answer already, TBH, I am not sure I do understand your problem exactly. I have some code that has a comment that says (above 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?

3 Comments

AllocConsole is only useful if you want to create a new console. The OP wants to use the existing console (if there is one) or to not have a console at all (if there isn't).
I tried using AttachConsole(ATTACH_PARENT_PROCESS), it wil open new cmd window. My problem statement is i open a cmd window and go to location where my exe is present (C:\test.exe) then run exe from same cmd window. On including AttachConsole() output is displayed in new cmd window.
@user1881297: well, that shouldn't happen. AttachConsole() isn't supposed to create a new console! Can you give us an MCVE?
0

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;
}

2 Comments

AllocConsole is only useful if you want to create a new console. The OP wants to use the existing console (if there is one) or to not have a console at all (if there isn't).
I tried using AttachConsole(ATTACH_PARENT_PROCESS), it wil open new cmd window. My problem statement is i open a cmd window and go to location where my exe is present (C:\test.exe) then run exe from same cmd window. On including AttachConsole() output is displayed in new cmd window.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.