Подтвердить что ты не робот

Как определить, была ли перенаправлена ​​Console.In(stdin)?

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

Возможно ли это? Какой самый элегантный способ сделать это на С#?

4b9b3361

Ответ 1

Вы можете узнать по p/вызову функции API FileType() Windows. Здесь класс-помощник:

using System;
using System.Runtime.InteropServices;

public static class ConsoleEx {
    public static bool IsOutputRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdout)); }
    }
    public static bool IsInputRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdin)); }
    }
    public static bool IsErrorRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stderr)); }
    }

    // P/Invoke:
    private enum FileType { Unknown, Disk, Char, Pipe };
    private enum StdHandle { Stdin = -10, Stdout = -11, Stderr = -12 };
    [DllImport("kernel32.dll")]
    private static extern FileType GetFileType(IntPtr hdl);
    [DllImport("kernel32.dll")]
    private static extern IntPtr GetStdHandle(StdHandle std);
}

Использование:

bool inputRedirected = ConsoleEx.IsInputRedirected;

UPDATE: эти методы были добавлены в класс Console в .NET 4.5. Без атрибуции я мог бы добавить:( Просто используйте соответствующий метод вместо этого вспомогательного класса.

https://msdn.microsoft.com/en-us/library/system.console.isoutputredirected.aspx https://msdn.microsoft.com/en-us/library/system.console.isinputredirected.aspx https://msdn.microsoft.com/en-us/library/system.console.iserrorredirected.aspx

Ответ 2

Интересно, что когда канал открыт, параметры System.Console.WindowHeight и System.Console.WindowWidth ноль, которые я обнаружил из-за нескольких ArgumentOutOfRangeException в кодах, которые не заботились о консоли размер которого равен нулю.

Crossplatform. Поведение такое же в MS dotNET и Моно в Linux и Windows (я не пробовал его на Mac).

Когда STDIN или STDOUT передаются по каналам, размер консоли устанавливается равным 0. Таким образом, построение по реализации Ханса, мой код выглядит следующим образом:

using System;


 public static class ConsoleEx {
        public static bool IsConsoleSizeZero {
            get {
                try {
                    return (0 == (Console.WindowHeight + Console.WindowWidth));
                }
                catch (Exception exc){
                    return true;
                }
            }
        }
        public static bool IsOutputRedirected {
            get { return IsConsoleSizeZero && !Console.KeyAvailable; }
        }
        public static bool IsInputRedirected {
            get { return IsConsoleSizeZero && Console.KeyAvailable; }
        }
}

Обновление 2016: Добавлена ​​обработка исключений в код IsConsoleSizeZero для улучшения удобства использования кода в более широком контексте.

Код по-прежнему работает хорошо, по крайней мере, исходя из опыта, используя MonoDevelop/Xamarin Studio.

Похожие

Ответ 4

Ответ Лоренца - хорошее начало, но, к сожалению, можно использовать только вдохновение. Существует больше режимов для запуска консольного приложения.

  • Стандартный запуск (в консоли без какого-либо перенаправления)

    В консоли все работает так, как ожидалось.

  • Выполнение с перенаправлением с консоли со стандартным вводом и/или стандартным перенаправлением вывода

    например.

    type input_file.txt | application.exe Windows) или application.exe <input_file.txt для перенаправления ввода

    (замените type на cat в Linux)

    или

    application.exe | grep pattern или application.exe >output_file.txt для перенаправления вывода

    или

    type input_file.txt | application.exe | grep pattern или application.exe <input_file.txt >output_file.txt для перенаправления ввода и вывода

  • Выполнение с перенаправлением с консоли со стандартным выходом и перенаправление выходных данных

    например. application.exe >output_file.txt 2>error_file.txt

  • Выполнение со скрытой консолью и перенаправлением ввода/вывода/ошибки

    например. из приложения GUI (консоль вообще не видима)

  • Выполнение со скрытой консолью без перенаправления ввода/вывода/ошибки

Каждый из этих режимов имеет свои собственные функции. Console.WindowHeight и Console.WindowWidth работают в Windows для 1-го и 2-го режимов стандартным способом. В Linux возвращаемое значение во втором и третьем режимах равно нулю. Поэтому в Linux вы не можете обнаружить перенаправление ввода только.

Поэтому код из ответа Лоренца не может использоваться для обнаружения перенаправления во всех случаях. IOException при чтении Console.WindowHeight или Console.WindowWidth вызывается только тогда, когда в консоли нет вывода <3 → и только для Windows.

Для обнаружения перенаправления ввода (только в Windows) используйте эту функцию:

private static bool IsInputRedirected()
{
  try
  {
    if (Console.KeyAvailable)
    {
      return (false);
    }
  }
  catch (InvalidOperationException)
  {
    return (true);
  }
  return (false);
}

Для всех других перенаправлений и операционных систем... попробуйте поэкспериментировать с их обнаружением. Различные свойства консоли и функции "работают" (исключение исключения или нулевые значения возврата) для разных режимов.

Протестировано на Windows 7 .NET Framework 4 Client Profile и Mono JIT compiler version 4.2.1 (Debian 4.2.1.102+dfsg2-7ubuntu4).

ВАЖНО:

Не используйте эту функцию для перенаправления ввода в Linux (обнаружите, что работает ОС/платформа, например Mono для Windows), потому что это может вызвать дополнительные проблемы, если вы ошибочно ожидаете перенаправления и перенаправление неактивно.