Как определить, был ли перенаправлен файл Console.In (stdin)? - PullRequest
25 голосов
/ 11 августа 2010

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

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

Ответы [ 4 ]

49 голосов
/ 11 августа 2010

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

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;

ОБНОВЛЕНИЕ: эти методы были добавлены в класс консоли в .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

5 голосов
/ 21 сентября 2012

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

Кроссплатформенность : Поведение MS dotNET и Mono в Linux и Windows одинаково (* я не пробовал на Mac). 1014 *

Когда передаются по каналу 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.

Относящиеся

1 голос
/ 13 января 2018

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

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

    В консоли все работает как положено.

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

    например,

    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 для перенаправления ввода и вывода

  3. Выполнение с перенаправлением с консоли со стандартным выходом и ошибка перенаправления вывода

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

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

    например, из приложения с графическим интерфейсом (консоль вообще не видна)

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

Каждый из этих режимов имеет свои «функции».Console.WindowHeight и Console.WindowWidth работают в Windows для 1-го и 2-го режимов стандартным способом.В Linux возвращаемое значение во 2-м и 3-м режимах равно ноль .Поэтому в 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) , поскольку это может вызвать больше проблем, когда вы ложно ожидаете перенаправленияи перенаправление не активно.

1 голос
/ 13 января 2017

Поскольку фреймворк 4.5 существует, свойство Console.IsInputRedirected.8 -)

См. MSDN

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

...