Правильный способ реализации консольного приложения C #? - PullRequest
20 голосов
/ 07 мая 2009

Как правильно реализовать и спроектировать инструмент командной строки как консольное приложение C #?

Проблемы, связанные с обращением, включают правильный анализ переменных командной строки и правильный способ вывода текста. Хотя Console.WriteLine () является наиболее очевидным выбором для вывода, каковы обстоятельства, при которых вместо этого следует выбрать запись в стандартный поток ошибок:

Как правильно выйти из приложения при возврате правильного кода возврата вызывающей команде?

Как должно быть реализовано событие CancelKeyPress для прерывания программы? Это только для использования, когда асинхронная операция происходит в отдельном потоке?

Существует ли краткое руководство по программированию инструментов командной строки в C # или, что еще лучше, проект или шаблон с открытым исходным кодом, которые я мог бы использовать для правильной реализации относительно простого инструмента?

Ответы [ 5 ]

25 голосов
/ 07 мая 2009

Сообщения об ошибках должны быть записаны в stderr, иначе Console.Error, и нормально выводиться в стандартный вывод, также известный как Console.Out. Это особенно важно для консольных приложений типа «фильтр», чей вывод (stdout) может быть передан другому процессу, например, в командном файле.

Обычно, если вы столкнулись с ошибкой, напишите сообщение об ошибке в Console.Error и верните ненулевой результат. Или, если это исключение, просто не беспокойтесь об этом.

Чтобы вернуть код результата, вы можете передать его в качестве аргумента в Environment.Exit, установить свойство Environment.ExitCode или вернуть ненулевое значение из main.

Для простых консольных приложений я бы:

  • имеет вспомогательный класс для разбора командной строки.

  • имеет класс фасадов, который предоставляет тестируемый API для функциональности, реализованной вашим инструментом командной строки. Как и для большинства .NET API, при возникновении ошибки обычно выдается исключение.

  • основная программа просто использует помощник для анализа командной строки и вызывает API, передавая аргументы, переданные из командной строки. Он может перехватывать исключения, генерируемые API, регистрировать их, записывать пользовательское сообщение об ошибке в Console.Error и устанавливать ненулевой код возврата.

Но я не считаю, что это единственно верный путь: на самом деле такого нет, поэтому вряд ли вы найдете книгу, которую ищете.

5 голосов
/ 07 мая 2009

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

[Command("quit")]
public void QuitApp()
{
    ...
}

При запуске программы вы можете отсканировать класс для таких методов и сохранить делегатов, которые нацелены на них, в словаре, где ключи являются командами. Это облегчает синтаксический анализ команд на основе поиска первого слова в словаре (амортизированный O (1)) и может легко расширяться и обрабатываться в будущем, поскольку новые команды добавляются простым добавлением отдельных методов.

2 голосов
/ 07 мая 2009

Для обработки командной строки, проверьте Mono.GetOptions. Это позволяет легко заполнять переменные из короткой (-f style) и длинной (--file style) опций командной строки.

2 голосов
/ 07 мая 2009

Что касается аргументов командной строки, вы найдете различные схемы, но я всегда был фанатом

app.exe "self-explanatory arg" /noArgumentSwitch /argumentSwitch="argument"

Что касается кода возврата, вы можете изменить сигнатуру вашей функции Main(), чтобы она возвращала int вместо void. Это позволит вам при необходимости вернуть код вызывающему процессу.

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

0 голосов
/ 07 мая 2009

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

...