Как перенаправить стандатртые потоки?
От: Went  
Дата: 17.12.05 07:46
Оценка:
Нужно перенаправть STDOUT, например. Но не в файл или консоль, а в функцию, чтобы по каждому
cout << "Some Data"

Происходил вызов функции
void stoout_function(void* data_ptr, int size)
{
}


Но все должно работать не только с моим, но и процессами-наследниками, в.т.ч. консольными. Читал про MailSlots и про NamedPipes. Что в моем случае надо копать?
Re: Как перенаправить стандатртые потоки?
От: s_viy  
Дата: 17.12.05 11:52
Оценка:
Обычно перенаправление ввода-вывода производиться при запуске процесса. В Win32 — это CreateProcess. При вызове можно указать дескрипторы для stdin stdout и stderr. HANDLE используется любой, но я обычно использую неименованые каналы (pipes) см. CreatePipe
Re[2]: Как перенаправить стандатртые потоки?
От: Аноним  
Дата: 17.12.05 19:14
Оценка:
Здравствуйте, s_viy, Вы писали:

_>Обычно перенаправление ввода-вывода производиться при запуске процесса. В Win32 — это CreateProcess. При вызове можно указать дескрипторы для stdin stdout и stderr. HANDLE используется любой, но я обычно использую неименованые каналы (pipes) см. CreatePipe


Спасибо, посмотрел каналы, разобрался, но цели так и не добился. Если Вас не затруднит, разъясните, пожайлуста следующие моменты.

1. Допустим, я создал трубу. Хендлы назвал h_read и h_end. Какие мне надо ставть SECURITY_ATTRIBUTES, и что это такое?

2. Я написал:
SetStdHandle(STD_OUTPUT_HANDLE, h_write);

Означает ли это, что теперь весь стандартный вывод будет идти по этой трубе?

3. Я написал
std::cout << "Hello!";

Означает ли это, что я направил "Hello" в стандартный вывод?

4. Допустим, для варианта с CreateProcess все ясно. Но теперь я пишу
system("dir");

Как заставить вывод этой комманды идти не в консоль (которая сразу создается и пропадает), а идти в мою трубу. Когда я делал консоль сам (AllocConsole()), все порожденные процессы писали в мою консоль, как заставить их не создавать свою консоль, а писать в мою трубу?

Буду очень благодарен за ответы.
Re[3]: Как перенаправить стандатртые потоки?
От: Аноним  
Дата: 18.12.05 11:49
Оценка:
А>Спасибо, посмотрел каналы, разобрался, но цели так и не добился. Если Вас не затруднит, разъясните, пожайлуста следующие моменты.
А>1. Допустим, я создал трубу. Хендлы назвал h_read и h_end. Какие мне надо ставть SECURITY_ATTRIBUTES, и что это такое?
А>2. Я написал:
А>
А>SetStdHandle(STD_OUTPUT_HANDLE, h_write);
А>

А>Означает ли это, что теперь весь стандартный вывод будет идти по этой трубе?
А>3. Я написал
А>
А>std::cout << "Hello!";
А>

А>Означает ли это, что я направил "Hello" в стандартный вывод?
А>4. Допустим, для варианта с CreateProcess все ясно. Но теперь я пишу
А>
А>system("dir");
А>

А>Как заставить вывод этой комманды идти не в консоль (которая сразу создается и пропадает), а идти в мою трубу. Когда я делал консоль сам (AllocConsole()), все порожденные процессы писали в мою консоль, как заставить их не создавать свою консоль, а писать в мою трубу?
А>Буду очень благодарен за ответы.

1) SECURITY_ATTRIBUTES ставь NULL
2) Да
3) Да
4) Что Вам мешает использовать CreateProcess для "dir"? Может в вашем случае проще перенаправить потоки средствами коммандной строки посредством разделителья "|". Например: dir *.* | you.exe. В этом случае все данные которые раньше выводились на консоль будут перегаправлены на стандартный ввод you.exe.
Re[4]: Как перенаправить стандатртые потоки?
От: Went  
Дата: 19.12.05 08:29
Оценка:
Здравствуйте, Аноним, Вы писали:

А>1) SECURITY_ATTRIBUTES ставь NULL

А>2) Да
А>3) Да
А>4) Что Вам мешает использовать CreateProcess для "dir"? Может в вашем случае проще перенаправить потоки средствами коммандной строки посредством разделителья "|". Например: dir *.* | you.exe. В этом случае все данные которые раньше выводились на консоль будут перегаправлены на стандартный ввод you.exe.

Большое спасибо , узнал много нового.
Re[4]: Как перенаправить стандатртые потоки?
От: ekamaloff Великобритания  
Дата: 19.12.05 08:29
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>2. Я написал:

А>>
А>>SetStdHandle(STD_OUTPUT_HANDLE, h_write);
А>>

А>>Означает ли это, что теперь весь стандартный вывод будет идти по этой трубе?
А>>3. Я написал
А>>
А>>std::cout << "Hello!";
А>>

А>>Означает ли это, что я направил "Hello" в стандартный вывод?

А>2) Да

А>3) Да

2) Нет
3) Нет

Простой тест:

#include "stdafx.h"
#include "windows.h"
#include "conio.h"

int _tmain(int argc, _TCHAR* argv[])
{
    DWORD dwWritten;
    char szBuf[64];
    HANDLE hFile = CreateFile("test.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    HANDLE hOldStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    SetStdHandle(STD_OUTPUT_HANDLE, hFile);

    std::cout<<"std::cout\n";
    printf("printf\n");
    strcpy(szBuf, "WriteFile");
    WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), szBuf, strlen(szBuf),
        &dwWritten, NULL);

    SetStdHandle(STD_OUTPUT_HANDLE, hOldStdOut);
    CloseHandle(hFile);
    getch();

    return 0;
}


Выводит

WriteFile

в файл test.txt и

std::cout
printf

на консоль.

Что я делаю не так?
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[5]: Как перенаправить стандатртые потоки?
От: Went  
Дата: 19.12.05 10:32
Оценка:
Здравствуйте, ekamaloff, Вы писали:

E>2) Нет

E>3) Нет

....

E>Что я делаю не так?


Да, вот и я с этим столкнулся. По-моему логика стандартных потоков не совсем дружит с WINAPI ухищерениями.
Re[5]: Как перенаправить стандатртые потоки?
От: Аноним  
Дата: 19.12.05 14:56
Оценка: 6 (1)
Проблема в том, что при создании процесса создается HANDLE’s стандартных потоков и их дескрипторы (1,2 и 3). В начале они совпадают, но SetStdHandle переопределяет только HANDLE’s. Здесь скрыт еще подвох в том, что WriteFile не буферизирует данные при записи в файл, а cout буферизирует… Короче, если не хотите геморроя, то не мешайте API вызовы, Run-Time и STL.

#include <io.h>
#include "stdafx.h"
#include "windows.h"
#include "conio.h"
#include "FCNTL.H"

int _tmain(int argc, _TCHAR* argv[])
{
    DWORD dwWritten;
    char szBuf[64];
    HANDLE hFile = CreateFile("test.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    HANDLE hOldStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    SetStdHandle(STD_OUTPUT_HANDLE, hFile);
    int old = _dup(1 );
    // Открываем существующий HANDLE как дескриптор 
    int newDescr = _open_osfhandle((intptr_t)hFile, _O_APPEND );
    // Переназначаем файловый дескриптор
    _dup2(newDescr, 1);
    std::cout<<"std::cout\n";
    printf("printf\n");
    strcpy(szBuf, "WriteFile\n");
    WriteFile(hFile, szBuf, strlen(szBuf), &dwWritten, NULL);
    // Сбрасываем поток 
    fflush( stdout );
    SetStdHandle(STD_OUTPUT_HANDLE, hOldStdOut);
    CloseHandle(hFile);
    
    _dup2(old, 1 );
    std::cout<<"std::cout\n";
    flushall();
    getch();

    return 0;
}
Re[6]: Как перенаправить стандатртые потоки?
От: Went  
Дата: 20.12.05 13:22
Оценка:
Здравствуйте, Аноним.

Спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.