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

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

Является ли это возможным? Какой самый элегантный способ сделать это на C #?

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

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: эти методы были добавлены в class Console в .NET 4.5. Без атрибуции я мог бы добавить 🙁 Просто используйте соответствующий метод вместо этого вспомогательного classа.

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

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

Crossplatform : поведение одинаково в MS dotNET и Mono на Linux и Windows (я не пробовал это на Mac).

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

 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.

Связанные :

  • MSDN: KeyAvailable

  • Установка System.Console.WindowHeight вызывает System.NotSupportedException в Mono .

Поскольку в структуре 4.5 существует свойство Console.IsInputRedirected. 😎

См. MSDN

https://msdn.microsoft.com/de-de/library/system.console.isinputredirected(v=vs.110).aspx

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

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

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

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

    например

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

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

    или

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

    или

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

  3. Выполнение с redirectм с консоли со стандартным выходом и переназначением выходных данных

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

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

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

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

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

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

Чтобы обнаружить redirect ввода (только в 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) , потому что это может вызвать дополнительные проблемы, когда вы ошибочно ожидаете перенаправления и redirect неактивно.

  • запустить exe / process с stdin stdout и stderr?
  • Как читать из файла или stdin в Bash?
  • Как читать из stdin с помощью fgets ()?
  • Использование fseek с указателем файла, указывающим на stdin
  • setvbuf не может сделать stdin небуферизованным
  • Как читать из stdin по строкам в узле
  • Запуск внешней программы с перенаправленным stdin и stdout из Java
  • Как заставить ssh получить пароль от stdin
  • Почему я получаю «Необработанный тип исключения IOException»?
  • Обнаруживать, является ли stdin терминалом или трубой?
  • Чтение двоичных данных из std :: cin
  • Давайте будем гением компьютера.