Изменить дескриптор функций ввода-вывода консоли по умолчанию - PullRequest
0 голосов
/ 12 мая 2010

Можно ли как-то изменить дескриптор стандартных функций ввода-вывода в Windows? Предпочитаемый язык - C ++. Если я правильно понимаю, выбирая консольный проект, компилятор просто предварительно выделяет консоль для вас и управляет всеми стандартными функциями ввода-вывода для работы с ее дескриптором. Итак, я хочу, чтобы одно консольное приложение фактически записывало в буфер консоли другого приложения. Я подумал, что мог бы получить первый дескриптор консоли, а затем передать его второму приложению с помощью файла (я мало знаю о межпроцессном взаимодействии, и это кажется простым) и чем-то использовать, например, prinf с первым дескриптором приложения. Можно ли это сделать? Я знаю, как получить дескриптор консоли, но я не знаю, как перенаправить printf на этот дескриптор. Это просто учебный проект, чтобы лучше понять работу ОС. Меня интересует, как printf знает, с какой консолью она связана.

Ответы [ 3 ]

1 голос
/ 13 мая 2010

Если я вас правильно понимаю, звучит так, будто вам нужна функция Windows API AttachConsole(pid), которая присоединяет текущий процесс к консоли, принадлежащей процессу с PID pid.

0 голосов
/ 13 мая 2010

Если я правильно вас понял, вы можете найти исходный код приложения, которое вы хотите написать, в http://msdn.microsoft.com/en-us/library/ms682499%28VS.85%29.aspx.. В этом примере показано, как написать stdin другого приложения и прочитать его stdout. * 1005. *

Для общего понимания. Компилятор не «предварительно выделяет консоль для вас». Компилятор использует стандартные библиотеки C / C ++, которые записывают в вывод. Так, если вы используете, например, printf(), следующий код будет выполнен в конце и будет выглядеть так:

void Output (PCWSTR pszwText, UINT uTextLenght) // uTextLenght is Lenght in charakters
{
    DWORD n;
    UINT uCodePage = GetOEMCP();    // CP_OEMCP, CP_THREAD_ACP, CP_ACP
    PSTR pszText = _alloca (uTextLenght);

    // in the console are typically not used UNICODE, so
    if (WideCharToMultiByte (uCodePage,  0, pszwText, uTextLenght,
                             pszText, uTextLenght, NULL, NULL) != (int)uTextLenght)
        return;

    WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), pszText, uTextLenght, &n, NULL);
    //_tprintf (TEXT("%.*ls"), uTextLenght, pszText);
    //_puttchar();
    //fwrite (pszText, sizeof(TCHAR), uTextLenght, stdout);
    //_write (
}

Таким образом, если изменить значение STD_OUTPUT_HANDLE, все выходные данные будут направлены в файл / канал и так далее. Если вместо WriteFile программа использует функцию WriteConsole, такое перенаправление не будет работать, но стандартная библиотека C / C ++ этого не делает.

Если вы хотите перенаправить stdout не из дочернего процесса, а из текущего процесса, вы можете вызвать SetStdHandle() напрямую (см. http://msdn.microsoft.com/en-us/library/ms686244%28VS.85%29.aspx).

«Распределение консоли» делает загрузчик операционной системы. Он просматривает слово бинарного EXE-файла (в части «Подсистема» IMAGE_OPTIONAL_HEADER см. http://msdn.microsoft.com/en-us/library/ms680339%28VS.85%29.aspx), и если в этом месте у EXE 3 (IMAGE_SUBSYSTEM_WINDOWS_CUI), чем он использует консоль родительского процесса или создает новый. Это поведение можно немного изменить в параметрах вызова CreateProcess (но только если вы запускаете дочерний процесс в своем коде). Это Subsystem флаг EXE, который вы определяете в отношении переключателя / подсистемы компоновщика (см. http://msdn.microsoft.com/en-us/library/fcc1zstk%28VS.80%29.aspx).

0 голосов
/ 13 мая 2010

Если вы хотите перенаправить printf на дескриптор (FILE *), просто выполните

fprintf(handle, "...");

Например, реплицируйте printf с fprintf

fprintf(stdout, "...");

илисообщение об ошибке

fprintf(stderr, "FATAL: %s fails", "smurf");

Это также, как вы пишете в файлы.fprintf(file, "Blah.");

...