Проверьте, перенаправлен ли вывод

У меня есть консольное приложение, написанное на С#, которое обрабатывает некоторые данные, а затем печатает результаты. Пока результаты не доступны, есть небольшая анимация ( / - \ | ) и процент прогресса ( xx %), который постоянно обновляется.

Очевидно, что если пользователь перенаправляет вывод моего приложения, он будет напечатан в текстовом файле, куда перенаправляется вывод. Если возможно, я хотел бы избежать этого.

Итак, есть ли способ определить, перенаправлен ли вывод моего приложения? Я рассматриваю возможность отображения индикаторов прогресса только при запуске с указанным параметром, но я надеюсь, что у кого-то будет хороший ответ для меня.


person Nippysaurus    schedule 23.07.2009    source источник
comment
Интересно прочитать ваш вопрос три года спустя и понять, насколько это было глупо :-) если кто-то читает это ... правильный подход к этому, безусловно, не показывать индикатор выполнения по умолчанию ... отображать его только тогда, когда используется специальный переключатель.   -  person Nippysaurus    schedule 27.07.2012
comment
возможный дубликат Как я могу определить, был ли Console.Out перенаправлен в файл?   -  person Kate Gregory    schedule 28.12.2012


Ответы (7)


Вы не можете. Перенаправленный вывод целиком и полностью выходит за рамки исполняемой программы. Однако вы можете добавить параметр командной строки, чтобы отключить красивый вывод, чтобы его можно было использовать и для перенаправления.

EDIT: вы МОЖЕТЕ (сейчас)... с .NET 4.5 и выше (см. ответ Мэтта Брукса).

person Matthew Scharley    schedule 23.07.2009
comment
Как я и думал ›.‹ Возможно, просто нужно использовать параметр cli. - person Nippysaurus; 23.07.2009
comment
Что, если я хочу угадать некоторые настройки по умолчанию в зависимости от того, идет ли ввод с консоли или нет? Например, в парсере SQL хорошо выводить результирующий набор записей при приеме команд с клавиатуры, но молчать при разборе файла. Или что, если мне нужно вывести спецификацию Unicode при записи в файл? Какие шаблоны следует использовать в этих случаях? - person himself; 23.08.2010
comment
@himself: Если вы хотите обрабатывать такие вещи, как написание спецификации, попросите выходной параметр. В зависимости от ОС вы можете определить, работаете ли вы на консоли, но это, мягко говоря, запутанно, и я не думаю, что это работает в Windows/C#. Ваша самая простая ставка - принять -q (тихий) или аналогичный вариант или, возможно, предположить, что вы получаете запрограммированный ввод, если у вас есть указанная опция для записи в файл. - person Matthew Scharley; 23.08.2010

Начиная с .NET Framework 4.5, вы можете использовать Console.IsOutputRedirected свойство, чтобы обнаружить это.

Есть также Console.IsErrorRedirected.

person Matt Brooks    schedule 13.08.2015

Как выяснилось, вскоре он будет доступен в элегантном и кросс-платформенном виде: ссылка.

person konrad.kruczynski    schedule 04.12.2011

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

Этот метод предлагается в примечаниях к документации для WriteConsole:

... определить, является ли выходной дескриптор дескриптором консоли (один из методов - вызвать функцию GetConsoleMode и проверить, успешно ли она выполнена)...

person Stobor    schedule 23.07.2009
comment
Конечно, это означает использование небезопасных нативных методов... Но это возможно. - person Stobor; 23.07.2009
comment
Некоторые свойства вызывают GetConsoleMode и бросают вызов при сбое, например Console.CursorVisible. Это позволило бы проверять вывод консоли без использования P/Invoke. - person Medinoc; 05.05.2017

Вместо того, чтобы пытаться определить, перенаправлен ли контент, я бы использовал Console.WriteLine (или Console.Out.WriteLine) для печати ваших результатов и Console.Error.Write для обновлений вашего статуса. Вывод на экран будет отображаться правильно, но не будет отражен в текстовом файле.

person DocMax    schedule 23.07.2009
comment
Хорошая идея, однако запись данных без ошибок в stderr может ввести в заблуждение. - person Nippysaurus; 23.07.2009
comment
Вводит в заблуждение, да, но все же обычная практика. - person Matthew Scharley; 23.07.2009

Наверное, можно попробовать так:

public enum FileType : uint
{
    FILE_TYPE_UNKNOWN = 0x0000,
    FILE_TYPE_DISK = 0x0001,
    FILE_TYPE_CHAR = 0x0002,
    FILE_TYPE_PIPE = 0x0003,
    FILE_TYPE_REMOTE = 0x8000,
}

public enum STDHandle : uint
{
    STD_INPUT_HANDLE = unchecked((uint)-10),
    STD_OUTPUT_HANDLE = unchecked((uint)-11),
    STD_ERROR_HANDLE = unchecked((uint)-12),
}

[DllImport("Kernel32.dll")]
static public extern UIntPtr GetStdHandle(STDHandle stdHandle);
[DllImport("Kernel32.dll")]
static public extern FileType GetFileType(UIntPtr hFile);

static public bool IsOutputRedirected()
{
    UIntPtr hOutput = GetStdHandle(STDHandle.STD_OUTPUT_HANDLE);
    FileType fileType = (FileType)GetFileType(hOutput);
    if (fileType == FileType.FILE_TYPE_CHAR)
        return false;
    return true;
}

Если стандартный вывод не перенаправляется, вывод GetFileType() должен быть 0x0002. Это работает для меня. :)

person Elliott    schedule 10.05.2013

Console.Write("whatever") (и WriteLine) фактически записывают данные в поток за Console.Out. Чтобы всегда отображать индикатор выполнения на консоли и не записывать его в файл, независимо от того, перенаправляется вывод в файл или нет, вместо этого используйте поток ошибок:

Console.Error.Write("<your progress bar>");

Когда приложение перенаправляет вывод с помощью оператора > (DIR C:\*.*>MORE), перенаправляется только Console.Out, а не Console.Error

person AyrA    schedule 18.04.2014