Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > printf в неконсольном приложении


Автор: Dem_max 14.5.2013, 15:57
Как в не консольном (в своем же процессе) приложении перехватить то что выводит printf.
И если существует StdIn и StdOut для не консольного приложения как его перехватить и вывести в тот же Edit

Автор: GremlinProg 15.5.2013, 07:04
Цитата(Dem_max @  14.5.2013,  17:57 Найти цитируемый пост)
в не консольном

думаю, в таком случае надежнее будет использовать пайпы

Добавлено через 28 секунд
а не StdIn и StdOut

Автор: Dem_max 15.5.2013, 07:33
Пробовал так
Код

#define BUFSIZE     100
TCHAR chBuf[BUFSIZE];
 
    hStdin = GetStdHandle(STD_INPUT_HANDLE);
        if(hStdin == INVALID_HANDLE_VALUE)
        OutputDebugString("GetStdHandle");
 
    for(;;)
    {
 
        if(!ReadConsole(hStdin, chBuf, BUFSIZE, &dwRead, NULL))
        //if(!ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL))
        {
            wsprintf(txt, "ReadConsole FAIL = %0X", GetLastError());
            OutputDebugString(txt);
        }
    }


но возвращается ReadConsole FAIL = 8


Собственно к чему замут то, имею python.dll из которой вызываю функции и передаю им имя скрипта на выполнение, но результата не вижу. Нужно как то получать выполнения скрипта питона.

Автор: DarthTon 15.5.2013, 11:31
У меня работает как-то так:

Код

#include <tchar.h>
#include <stdio.h>
#include <Io.h>
#include <Fcntl.h>
#include <windows.h>

DWORD CALLBACK ThdProc(LPVOID /*lpParam*/)
{
    DWORD dwBytes = 0;
    char buf[0x1000] = {0};

    HANDLE hPipe = CreateFile(_T("\\\\.\\pipe\\SomePipeName"), 
        GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);

    if(hPipe != INVALID_HANDLE_VALUE)
    {
        //for(;;)
        {
            DWORD dwBytes = 0;
            DWORD dwLeft  = 0;
            DWORD dwOfst  = 0;

            ReadFile(hPipe, buf, 0x1000, &dwBytes, NULL);

            dwOfst = dwBytes;

            PeekNamedPipe(hPipe, NULL, NULL, NULL, &dwLeft, 0);

            while(dwLeft > 0)
            {
                ReadFile(hPipe, buf + dwOfst, dwLeft, &dwBytes, NULL);
                dwOfst += dwBytes;

                PeekNamedPipe(hPipe, NULL, NULL, NULL, &dwLeft, 0);
            }

            MessageBoxA(NULL, buf, "Buffer", 0);
        }

        CloseHandle(hPipe);
    }

    return 0;
}

int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
    HANDLE hPipe = CreateNamedPipe(_T("\\\\.\\pipe\\SomePipeName"), PIPE_ACCESS_OUTBOUND,
        PIPE_TYPE_BYTE, 1, 0x1000, 0x1000, 0, NULL);

    if(hPipe != INVALID_HANDLE_VALUE)
    {
        HANDLE hThd = CreateThread(NULL, 0, &ThdProc, NULL, 0, NULL);

        if(hThd && ConnectNamedPipe(hPipe, NULL))
        {
            int pipeDesc = _open_osfhandle((intptr_t)hPipe, 0);

            if(pipeDesc > 0)
            {
                FILE *fp = _fdopen(pipeDesc, "w");

                if(fp)
                {
                    *stdout = *fp;
                    setvbuf(stdout, NULL, _IONBF, 0);

                    printf("This is test message\n");

                    WaitForSingleObject(hThd, INFINITE);
                    fclose(fp);
                }
            }
        }
    }
    
    return 0;
}


Тут возникают проблемы с буферизацией stdout, если её не отключить (setvbuf(stdout, NULL, _IONBF, 0)) то пайп ждёт либо полного заполнения буфера, либо надо флашить stdout вручную. В документации к setvbuf, однако, есть флаг _IOLBF, описание которого гласит 
Цитата

Line buffering: On output, data is written when a newline character is inserted into the stream or when the buffer is full (or flushed), whatever happens first. On Input, the buffer is filled up to the next newline character when an input operation is requested and the buffer is empty.

Но у меня он всё равно не заработал, как бы я не пытался отправить в поток newline character.

Автор: GremlinProg 15.5.2013, 12:46
Цитата(DarthTon @  15.5.2013,  13:31 Найти цитируемый пост)
Но у меня он всё равно не заработал, как бы я не пытался отправить в поток newline character.

а если не использовать CRT(printf), а писать в пайп с помощью WriteConsole?

Добавлено через 1 минуту и 18 секунд
или WriteFile?

Автор: DarthTon 15.5.2013, 14:59
При помощи WriteConsole можно писать только в консольные хендлы (GetStdHandle(STD_OUTPUT_HANDLE) и т.п.), для хендла пайпа оно возвращает Invalid Handle; подмена дефолтного STD_OUTPUT_HANDLE на хендл пайпа тоже не помогает . 
Я не тестировал WriteFile в пайп на больших сообщениях, но на маленьких всё работает как и должно . Проблемы только при использовании CRT с буферизацией. 

Автор: Dem_max 15.5.2013, 19:11
_open_osfhandl
это CRT от мелкомягких,  оно никак не подходит для других компиляторов.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)