Как указать код выхода консольного приложения в .NET?

471

У меня есть тривиальное консольное приложение в .NET. Это всего лишь тестовая часть более крупного приложения. Я хотел бы указать «код выхода» моего консольного приложения. Как мне это сделать?

MrDatabase
источник

Ответы:

599

3 варианта:

  • Вы можете вернуть его, Mainесли объявите свой Mainметод возврата int.
  • Вы можете позвонить Environment.Exit(code).
  • Вы можете установить код выхода , используя свойство: Environment.ExitCode = -1;. Это будет использоваться, если ничто другое не устанавливает код возврата или использует одну из других опций выше).

В зависимости от вашего приложения (консоли, службы, веб-приложения и т. Д.) Могут использоваться разные методы.

TheSoftwareJedi
источник
12
Для тех из вас, кто задается вопросом, почему это не работает в их случае, убедитесь, что ваш проект скомпилирован как «консольное приложение», а не как «приложение Windows».
Марсель Госселин
10
Что если у меня есть приложение WinForms, которое с некоторыми аргументами должно работать как консольное приложение?
Себагомез
5
Вы также можете просто напечатать программу для Мейна как int (заменить void на int) и использовать, например, «return -1;» вернуться из основной программы. Это более переносимо, чем Environment.Exit () (зависит от среды).
Вернер
14
@DannyBeckett По соглашению код выхода 0означает успех, а ненулевой означает сбой. return;указывает на успех через код завершения 0и return -1;указывает на ошибку.
allonhadaya
6
Вы также можете установить код выхода, используя свойства: Environment.ExitCode = -1;
t3b4n
270

В дополнение к ответам, охватывающим возвращение int's ... призыв к здравомыслию. Пожалуйста, укажите ваши коды выхода в перечислении, с флагами, если это необходимо. Это значительно упрощает отладку и обслуживание (и в качестве бонуса вы можете легко распечатать коды выхода на экране справки - у вас есть один из них, верно?).

enum ExitCode : int {
  Success = 0,
  InvalidLogin = 1,
  InvalidFilename = 2,
  UnknownError = 10
}

int Main(string[] args) {
   return (int)ExitCode.Success;
}
Марк Брэкетт
источник
46
Вы можете добавить, что значение «0» для «Успеха» не случайно, а фактически «стандартное» значение для этой ситуации.
Christian.K
39
ЭТО. Вот почему SO является лучшим сайтом в истории интернета. Этот совет не всегда доступен в любом учебнике, и его можно почерпнуть, только поговорив с опытным профессионалом. БЛАГОДАРЮ ВАС.
Даниэль Сзабо
17
Вы говорите, что 0 - это стандартное значение для успеха, и все же при преобразовании 0/1 в логическое значение 0 равно false, а 1 - true! Может быть точнее сказать, что код выхода 0 означает «нет ошибки», а не «успех», поскольку код выхода - это ErrorResult, а не просто Result.
Марк Шапиро
11
Полный список соглашений Microsoft см. По адресу msdn.microsoft.com/en-us/library/windows/desktop/… . Какой-то парень составил огромный список контстов и использовал его в переключателе в комментариях ниже.
Nawfal
5
@MarkShapiro, я думаю, 0 = Successисходит из того факта, что нужен только один код успеха, но многие коды ошибок, такие, что 0, не имеющие + или - в целых числах компьютера, могут быть использованы для уникальной идентификации успеха
Себастьян,
50

Есть три метода, которые вы можете использовать для возврата кода завершения из консольного приложения.

  1. Измените Mainметод в своем приложении так, чтобы он возвращал intвместо void(функция, которая возвращает Integerвместо вместо Subв VB.Net), а затем возвращал код выхода из этого метода.
  2. Установите для свойства Environment.ExitCode код завершения. Обратите внимание, что метод 1. имеет приоритет - если Mainметод возвращает что-либо кроме void(находится Subв VB.Net), тогда значение этого свойства будет игнорироваться.
  3. Передайте код завершения в метод Environment.Exit . Это немедленно прекратит процесс, в отличие от двух других методов.

Важный стандарт, который следует соблюдать, - это 0«Успех».

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

Также убедитесь, что ваше приложение скомпилировано как «Консольное приложение».

Скотт Мунро
источник
1
Это поднимает интересный момент. Установка Environment.ExitCodeне закрывает программу сразу, но Environment.Exitметод закрывает программу немедленно
PsychoData
1
Код выхода также работает в приложениях Windows. Если приложение будет запущено из c # через Processобъект, вы можете запросить объект WaitForExit(), а затем запросить у него код выхода.
Nyerguds
43

Если вы собираетесь использовать метод, предложенный Дэвидом, вам также следует взглянуть на атрибут [Flags].

Это позволяет вам делать побитовые операции над перечислениями.

[Flags]
enum ExitCodes : int
{
  Success = 0,
  SignToolNotInPath = 1,
  AssemblyDirectoryBad = 2,
  PFXFilePathBad = 4,
  PasswordMissing = 8,
  SignFailed = 16,
  UnknownError = 32
}

затем

(ExitCodes.SignFailed | ExitCodes.UnknownError)

будет 16 + 32. :)

Арон Цанг
источник
3
Это означает, что программа скажет «Ваш пароль неверен», затем попытается подписать все, что подписывает, и остановится только в случае неудачи. Вы должны вернуться после неудачи; все остальное является предупреждением, и программа должна все еще возвращать 0.
Пит Киркхем
3
Малоизвестным фактом является то, что [Flags] ничего не делает для включения или отключения побитовых операций. Все, что он делает - переопределяет метод ToString, чтобы выходные данные представляли побитовые флаги. С этим или без него вы все равно можете выполнять побитовые операции.
Стивен
3
@ Стивен, это приятно знать, но я все равно рекомендую украшать перечисления, предназначенные для «использования флага», этим атрибутом, если ничего другого не передает намерение.
MarioDS
25
int code = 2;
Environment.Exit( code );
бледная лошадь
источник
17
По любой технической причине вы не просто написали "Environment.Exit (2);" ?
Blorgbeard выходит
53
Присвоение магического числа переменной с бессмысленным именем не делает ее менее волшебной.
Blorgbeard выходит
11

Просто верните соответствующий код с основного.

int main(string[] args)
{
      return 0; //or exit code of your choice
}
Эстебан Арайя
источник
2
Консольное приложение C # по умолчанию вообще не объявляет main. Это объявляет static void Main(string[] args);
Марк Лаката
19
@ Марк Лакта: Тогда поменяй, нет?
Эстебан Арайя
11

Используйте ExitCode, если ваш main имеет подпись возврата void, в противном случае вам нужно «установить» его на возвращаемое вами значение.

Свойство Environment.ExitCode

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

crashmstr
источник
8

Как обновление ответа Скотта Мунро :

  • В C # 6.0 и VB.NET 14.0 (VS 2015) для возврата ненулевого кода из консольного приложения требуется либо Environment.ExitCode, либо Environment.Exit (exitCode) . Изменение типа возврата не Mainимеет никакого эффекта.
  • В F # 4.0 (VS 2015) возвращаемое значение mainточки входа соблюдается.
Vern DeHaven
источник
Можно ли подтвердить ваш 1-й пункт относительно C # 6? Кажется, я ничего не могу найти в Интернете. Возвращаемое значение из функции Main прикрепляется к коду завершения процесса (по крайней мере, во всех предыдущих компиляторах), почему они должны были это изменить?
Арман Макхитариан,
Чистое неподтвержденное свидетельство, но я просто столкнулся с этим в моей собственной библиотеке, где простое возвращение моего кода результата / ошибки Main()не установило то, Process.ExitCodeчто было видно вызывающим приложением.
Маркус Мангельсдорф
MSDN утверждает, int Mainчто все еще может использоваться в качестве альтернативы Environment.ExitCode. ссылка
Арман Макхитариан
У меня есть приложение, которое запускает несколько потоков. В определенных обстоятельствах мне необходимо закрыть некоторые потоки с помощью Thread.Abort () перед выходом из приложения. В этих условиях int Main () {... thread.Abort (); ... return 0;} НЕ приводит к коду завершения процесса 0: код завершения процесса равен -1. Похоже, что при определенных обстоятельствах MS решила, что соглашение об использовании возвращаемого значения основного потока для установки кода выхода процесса недостаточно для них. Честно говоря, это может быть проблема с синхронизацией: прерывание потока может быть очень поздно в процессе установки кода выхода.
Дэвид И. Макинтош
7

Опция перечисления превосходна, но может быть улучшена путем умножения чисел как в:

enum ExitCodes : int
{
  Success = 0,
  SignToolNotInPath = 1,
  AssemblyDirectoryBad = 2,
  PFXFilePathBad = 4,
  PasswordMissing = 8,
  SignFailed = 16,
  UnknownError = 32
}

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

Например, уровень ошибки 6 может состоять только из ошибок 4 и 2, 12 может состоять только из ошибок 4 и 8, 14 может состоять только из 2, 4 и 8 и т. Д.

Дэвид
источник
2
Это если вы потрудитесь проверить дальнейшие ошибки после того, как столкнетесь с одной из них. Большинство приложений этого не делают.
Nyerguds
3

Мои 2 цента:

Вы можете найти коды системных ошибок здесь: https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx

Вы найдете типичные коды, такие как 2 для «файл не найден» или 5 для «доступ запрещен».

И когда вы наткнетесь на неизвестный код, вы можете использовать эту команду, чтобы выяснить, что это значит:

net helpmsg decimal_code

например

net helpmsg 1

возвращается

Неправильная функция

Фред Маурой
источник
0

Используйте этот код

Environment.Exit(0);

используйте 0 как int, если вы не хотите ничего возвращать.

Свастик бхаттачарья
источник
Это не ответ на вопрос OP, и возвращение 0 означает возвращение чего-то ...
PL