Как запустить консольное приложение C # со скрытой консолью

142

Есть ли способ скрыть окно консоли при выполнении консольного приложения?

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

Аарон Томас
источник
попробуйте запустить консольное приложение из запланированной задачи.

Ответы:

159

Если вы используете ProcessStartInfoкласс, вы можете установить стиль окна как скрытый - в случае консольных (не GUI) приложений вы должны установить CreateNoWindow на true:

System.Diagnostics.ProcessStartInfo start =
      new System.Diagnostics.ProcessStartInfo();
start.FileName = dir + @"\Myprocesstostart.exe";
start.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; //Hides GUI
start.CreateNoWindow = true; //Hides console
Адам Марковиц
источник
26
Именно то, что я собирался опубликовать :)
Джон Скит,
76
Черт возьми - кто-то быстрее Джона! =)
Эрик Форбс
76
Мне пришлось задушить его интернет-соединение, чтобы победить его;)
Адам Марковиц
11
Это не сработало для вызова инструмента командной строки. Используется yourprocess.StartInfo.CreateNoWindow = true; вместо этого см. ниже.
Christian
12
Не скрывает окно консоли, требуется StartInfo.CreateNoWindow = true.
Дэниел
204

Если вы написали консольное приложение, вы можете сделать его скрытым по умолчанию.

Создайте новое консольное приложение, затем измените тип «Тип вывода» на «Приложение Windows» (выполняется в свойствах проекта).

Саймон
источник
7
Я пытался скрыть свою консоль, не вызывать что-то еще, а затем скрыть ее (как предполагает принятый ответ) - так что это был лучший вариант для меня. Благодарность!
iamserious
6
Спасибо дружище ! Это то, что я тоже искал!
Варун Шарма
3
Принятый ответ предполагает, что это указано в вопросе.
aqua
Самый простой способ .. очень понравилось .. мы, конечно, не хотим показывать окно, потому что оно будет запускать из него другой процесс для меня ..
Сай Авинаш
1
Это позволяет обойти проблемы с ProcessStartInfo, где вы указываете учетные данные пользователя, и этот пользователь находится в системе или является текущим пользователем. В этой ситуации свойство CreateNoWindow игнорируется, поэтому вы всегда получаете окно консоли. Установив консольное приложение на приложение Windows, но без окна, вы не получите окна.
tjmoore
67

Если вы используете класс процесса, вы можете написать

yourprocess.StartInfo.UseShellExecute = false;
yourprocess.StartInfo.CreateNoWindow = true;

до yourprocess.start();и процесс будет скрыт

Питер Мортенсен
источник
4
Удачи, если вам нужно преждевременно остановить этот процесс. Process.Kill внезапно завершается. Process.CloseMainWindow не работает. GenerateConsoleCtrlEvent не может отправить процессу ctrl + c или ctrl + break. WM_CLOSE для всех окон потоков в процессе не выполняется. Кажется, нет способа полностью завершить процесс, начатый с этими двумя значениями параметров. См. Мой вопрос здесь: stackoverflow.com/questions/16139571/…
Трийнко
Спасибо, это было самым простым. Также, если у вас есть (или у вас) код для консоли, я обнаружил, что этот пример мьютекса является самым простым для чистого завершения работы. stackoverflow.com/a/31586184/1877412
cbuteau
1
@Triynko: Вы не можете полностью завершить какой-либо процесс, если этот процесс активно не взаимодействует. Это не вопрос флагов или чего-то еще. В ОС нет ничего, что могло бы вызвать полное отключение. Распространенным решением здесь является использование ожидаемого объекта ядра, о котором сигнализирует контролирующий процесс, когда подчиненный процесс должен завершиться. Подчиненный процесс должен активно контролировать состояние этого ожидающего объекта и инициировать чистое завершение работы после получения сигнала.
Inspectable,
43

Простой ответ: перейдите в свойства консольного приложения (свойства проекта). На вкладке «Приложение» просто измените «Тип вывода» на «Приложение Windows». Вот и все.

Джихан
источник
4
Яблочко. Это то же самое, что создать приложение Windows, которое не вызывает никаких форм.
ashes999
1
Это правильный ответ. Ни один из ваших других пластырей не подходит. Это действительно ПРАВИЛЬНЫЙ ответ. Вы хотите, чтобы ваше приложение никогда не открывало консоль. Кроме того, вы хотите иметь возможность открывать форму в любое время. Так что вы просто вызываете форму, когда хотите. т.е. наша форма вызывается, когда пользователь щелкает правой кнопкой мыши значок на панели задач и выбирает настройки. ЭТО ПРАВИЛЬНЫЙ ОТВЕТ !!!
Bluebaron
20

Вы можете использовать FreeConsole API, чтобы отсоединить консоль от процесса:

[DllImport("kernel32.dll")]
static extern bool FreeConsole();

(конечно, это применимо, только если у вас есть доступ к исходному коду консольного приложения)

Томас Левеск
источник
Хотел консоль не показывать. Хотя FreeConsoleделает то, что говорит его название, это не мешает Windows отображать консоль до ее вызова.
Jader Dias
5
Затем скомпилируйте проект как приложение Windows, а не консольное приложение
Томас Левеск,
1
Для справки, это именно то, что мне нужно, спасибо. Это также именно то, о чем и требует название :) Итак, в интересах других путешественников Google, +1
sehe 01
3
Вдобавок [DllImport("kernel32.dll")] static extern bool AllocConsole();позволяет легко запускать с консоли из стандартного приложения Win32
01
1
Работает для моего приложения .NET Core 2.2 - если кто-то специально это ищет.
Medismal
7

Если вас интересует вывод, вы можете использовать эту функцию:

private static string ExecCommand(string filename, string arguments)
{
    Process process = new Process();
    ProcessStartInfo psi = new ProcessStartInfo(filename);
    psi.Arguments = arguments;
    psi.CreateNoWindow = true;
    psi.RedirectStandardOutput = true;
    psi.RedirectStandardError = true;
    psi.UseShellExecute = false;
    process.StartInfo = psi;

    StringBuilder output = new StringBuilder();
    process.OutputDataReceived += (sender, e) => { output.AppendLine(e.Data); };
    process.ErrorDataReceived += (sender, e) => { output.AppendLine(e.Data); };

    // run the process
    process.Start();

    // start reading output to events
    process.BeginOutputReadLine();
    process.BeginErrorReadLine();

    // wait for process to exit
    process.WaitForExit();

    if (process.ExitCode != 0)
        throw new Exception("Command " + psi.FileName + " returned exit code " + process.ExitCode);

    return output.ToString();
}

Он запускает указанную программу командной строки, ожидает ее завершения и возвращает вывод в виде строки.

JCH2k
источник
4

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

Крис Брегг
источник
Но если все, что вам нужно, - это запускать процесс до его завершения, например, вызывая его из планировщика задач, тогда служба неудобна, поскольку продолжает существовать. В некоторых ситуациях очень удобно изменить тип вывода на Windows Application вместо альтернативного ProcessWindowStyle как скрытого.
subsci 08
2

Добавьте это в свой класс, чтобы импортировать файл DLL:

[DllImport("user32.dll")] 
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 

[DllImport("kernel32.dll")] 
static extern IntPtr GetConsoleWindow();

const int SW_HIDE = 0;
const int SW_SHOW = 5;

А затем, если вы хотите скрыть это, используйте эту команду:

 var handle = GetConsoleWindow();
 ShowWindow(handle, SW_HIDE);

А если хотите показать консоль:

var handle = GetConsoleWindow();
ShowWindow(handle, SW_SHOW);
ИДК ничего
источник
1
[DllImport ("user32.dll")] статический extern bool ShowWindow (IntPtr hWnd, int nCmdShow); [DllImport ("kernel32.dll")] статический extern IntPtr GetConsoleWindow (); const int SW_HIDE = 0; const int SW_SHOW = 5;
soulmachine
1

Я знаю, что отвечаю не совсем то, что вы хотите, но мне интересно, правильный ли вы вопрос задаете.

Почему бы вам не использовать:

  1. служба Windows
  2. создайте новый поток и запустите свой процесс на этом

Похоже, это лучшие варианты, если все, что вам нужно, - это запустить процесс.

Натан Куп
источник
3
Существует множество сценариев, в которых запуск служебного консольного приложения является вполне законным.
Адам Робинсон,
В моем случае требуется отдельный процесс из-за модели клиент / сервер, которую использует программное обеспечение, над которым я работаю.
Аарон Томас
Создание нового потока не всегда решает проблему. Бывают случаи, когда вам просто не нужно раздражающее окно в фоновом режиме. Кроме того, что, если у вас есть process.start в цикле, вы не сможете выполнить какую-либо работу, так как окна консоли всплывают прямо перед вами.
user890332 07
1
Я запускаю служебные консольные приложения без окон из Планировщика заданий. Нет необходимости в обслуживании и нет родительского процесса, из которого можно разветвлять поток. Эти приложения записывают в журнал событий, если требуется дополнительный вывод.
subsci 08
1

Хотя, как сказано в других ответах, вы можете изменить «Тип вывода» на «Приложение Windows», имейте в виду, что это будет означать, что вы не можете использовать, Console.Inпоскольку он станет NullStreamReader.

Console.Outи, Console.Errorпохоже, все еще работает нормально.

Kjbartel
источник
2
Ты серьезно? Зачем кому-то использовать, Console.Inкогда нет консоли, чтобы что-то вводить? Откуда взять что-нибудь, к чему можно получить доступ Console.In? В этом нет никакого смысла. Другими словами: Это совершенно очевидно и логично , что Console.Inявляется NullStreamReaderв данном случае.
Роберт С.
1
@RobertS. Может быть, трубка. Т.е. вывод другой программы. Это был мой случай использования, когда я это обнаружил.
kjbartel
1

Основываясь на ответе Адама Марковица выше, у меня сработало следующее:

process = new Process();
process.StartInfo = new ProcessStartInfo("cmd.exe", "/k \"" + CmdFilePath + "\"");
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
//process.StartInfo.UseShellExecute = false;
//process.StartInfo.CreateNoWindow = true;
process.Start();
Вулкан Бару
источник
1

У меня есть общее решение:

using System;
using System.Runtime.InteropServices;

namespace WhateverNamepaceYouAreUsing
{
    class Magician
    {
        [DllImport("kernel32.dll")]
        static extern IntPtr GetConsoleWindow();

        [DllImport("user32.dll")]
        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        const int HIDE = 0;
        const int SHOW = 5;

        public static void DisappearConsole()
        {
            ShowWindow(GetConsoleWindow(), HIDE);
        }
    }
}

Просто включите этот класс в свой проект и позвоните Magician.DisappearConsole();.

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

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

Я также попытался просто изменить настройки в Visual Studio> Project> Properties> Application для запуска в качестве приложения Windows вместо консольного приложения, и что-то в моем проекте помешало этому скрыть мою консоль - возможно, потому что DSharpPlus требует запуска консоли при запуске. . Я не знаю. Какой бы ни была причина, этот класс позволяет мне легко отключить консоль после ее появления.

Надеюсь, этот Волшебник кому-то поможет. ;)

Лукас Джарретт
источник
0

Просто пиши

ProcessStartInfo psi= new ProcessStartInfo("cmd.exe");
......

psi.CreateNoWindow = true;
Навин
источник