Jak uruchomić aplikację konsolową C # z ukrytą konsolą

141

Czy istnieje sposób na ukrycie okna konsoli podczas wykonywania aplikacji konsolowej?

Obecnie używam aplikacji Windows Forms do uruchamiania procesu konsoli, ale nie chcę, aby okno konsoli było wyświetlane, gdy zadanie jest uruchomione.

Aaron Thomas
źródło
spróbuj uruchomić aplikację konsolową z zaplanowanego zadania.

Odpowiedzi:

158

Jeśli korzystasz z ProcessStartInfoklasy, możesz ustawić styl okna na ukryty - w przypadku aplikacji konsolowych (nie GUI) musisz ustawić CreateNoWindow na 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
Adam Markowitz
źródło
26
Właśnie to miałem zamiar opublikować :)
Jon Skeet
75
O cholera - ktoś szybszy niż Jon! =)
Erik Forbes
75
Musiałem zdławić jego łącze internetowe, żeby go pokonać;)
Adam Markowitz
11
Nie działało przy wywoływaniu narzędzia wiersza poleceń. Used yourprocess.StartInfo.CreateNoWindow = true; zamiast tego zobacz poniżej.
Christian
12
Nie ukrywa okna konsoli, wymagany jest StartInfo.CreateNoWindow = true.
Daniel
201

Jeśli napisałeś aplikację konsoli, możesz ją domyślnie ukryć.

Utwórz nową aplikację konsolową, a następnie zmień typ „Typ wyjścia” na „Aplikacja systemu Windows” (można to zrobić we właściwościach projektu)

Szymon
źródło
6
Próbowałem ukryć własną konsolę, nie dzwonić do czegoś innego, a potem to ukrywać (tak jak zakłada przyjęta odpowiedź) - więc to była dla mnie najlepsza. dzięki!
iamserious
6
Dzięki stary ! Tego też szukałem!
Varun Sharma
3
Przyjęta odpowiedź zakłada, że ​​tak jest, ponieważ jest to określone w pytaniu.
aqua
Najprostszym way..really lubił it..we pewno nie chcesz, aby wyświetlić okno beacuse ma zamiar uruchomić inny proces z tego dla mnie ..
Sai Avinash
1
To pozwala obejść problemy z ProcessStartInfo, w których określasz poświadczenia użytkownika, a ten użytkownik jest zalogowany lub bieżący użytkownik. W takiej sytuacji właściwość CreateNoWindow jest ignorowana, więc zawsze pojawia się okno konsoli. Po ustawieniu aplikacji konsoli na aplikację Windows, ale bez okna, nie otrzymasz żadnego okna.
tjmoore
67

Jeśli używasz klasy Process, możesz pisać

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

przed yourprocess.start();i proces zostanie ukryty

Peter Mortensen
źródło
4
Powodzenia, jeśli musisz wcześniej zatrzymać ten proces. Process.Kill kończy się nagle. Błąd Process.CloseMainWindow. GenerateConsoleCtrlEvent nie może wysłać ctrl + c lub ctrl + break do procesu. WM_CLOSE do wszystkich okien wątków w procesie kończy się niepowodzeniem. Wydaje się, że nie ma sposobu na czyste zakończenie procesu rozpoczętego z tymi dwoma wartościami parametrów. Zobacz moje pytanie tutaj: stackoverflow.com/questions/16139571/…
Triynko
Dzięki ton, to było najprostsze. Również jeśli posiadasz (lub działasz) kod konsoli, ten przykład muteksu jest najłatwiejszy do czystego zamknięcia. stackoverflow.com/a/31586184/1877412
cbuteau
1
@Triynko: Nie możesz czysto zakończyć żadnego procesu, chyba że ten proces aktywnie współpracuje. To nie jest kwestia flag ani niczego innego. W systemie operacyjnym nie ma nic, co mogłoby spowodować czyste zamknięcie. Typowym rozwiązaniem jest tutaj użycie czekającego obiektu jądra, który jest sygnalizowany w procesie kontrolującym, kiedy proces slave powinien się zakończyć. Proces slave musi aktywnie monitorować stan tego oczekującego obiektu i zainicjować czyste zamknięcie po zasygnalizowaniu.
Niespodziewane
43

Prosta odpowiedź jest taka: przejdź do właściwości aplikacji konsoli (właściwości projektu). Na karcie „Aplikacja” po prostu zmień „Typ wyniku” na „Aplikacja Windows”. To wszystko.

Cihan
źródło
4
Strzał w dziesiątkę. To jest to samo, co tworzenie aplikacji Windows, która nie wywołuje żadnych formularzy.
popioły 999
1
To jest poprawna odpowiedź. Żaden z twoich innych bandaid się nie zbliża. To jest właściwa odpowiedź. Chcesz, aby Twoja aplikacja nigdy nie otwierała konsoli. Chcesz mieć możliwość otwarcia formularza w dowolnym momencie. Więc po prostu dzwonisz do formularza, kiedy chcesz. tzn. nasz formularz jest wywoływany, gdy użytkownik kliknie prawym przyciskiem myszy ikonę w zasobniku systemowym i wybierze preferencje. TO WŁAŚCIWA ODPOWIEDŹ !!!
Bluebaron
20

Możesz użyć FreeConsole API, aby odłączyć konsolę od procesu:

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

(oczywiście dotyczy to tylko sytuacji, gdy masz dostęp do kodu źródłowego aplikacji konsolowej)

Thomas Levesque
źródło
Chciałem nie pokazywać konsoli. Chociaż FreeConsolerobi to, co mówi jego nazwa, nie zapobiega wyświetlaniu konsoli przez system Windows przed jej wywołaniem.
Jader Dias
5
Następnie skompiluj projekt jako aplikację Windows, a nie aplikację konsolową
Thomas Levesque
1
Dla przypomnienia, jest to dokładnie to, co mi potrzebne, dzięki. To też jest dokładnie to , o co prosi tytuł :) Więc w interesie innych podróżników Google, +1
patrz
3
Ponadto [DllImport("kernel32.dll")] static extern bool AllocConsole();umożliwia łatwe uruchamianie z konsolą ze standardowej aplikacji Win32
patrz
1
Działa dla mojej aplikacji .NET Core 2.2 - jeśli ktoś szuka tego specjalnie.
Medismal
7

Jeśli jesteś zainteresowany wyjściem, możesz skorzystać z tej funkcji:

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();
}

Uruchamia podany program wiersza poleceń, czeka na jego zakończenie i zwraca wynik w postaci łańcucha.

JCH2k
źródło
4

Jeśli tworzysz program, który nie wymaga wprowadzania danych przez użytkownika, zawsze możesz go po prostu utworzyć jako usługę. Usługa nie wyświetla żadnego interfejsu użytkownika.

Chris Bregg
źródło
Ale jeśli wszystko, co chcesz zrobić, to uruchamiać proces aż do jego zakończenia, np. Wywołując go z Harmonogramu zadań, usługa jest niewygodna, ponieważ nadal istnieje. W niektórych sytuacjach zmiana typu danych wyjściowych na aplikację systemu Windows w porównaniu z alternatywnym ProcessWindowStyle jako ukrytym jest bardzo wygodna.
subskrybuje
2

Dodaj to do swojej klasy, aby zaimportować plik 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;

A jeśli chcesz to ukryć, użyj tego polecenia:

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

A jeśli chcesz pokazać konsolę:

var handle = GetConsoleWindow();
ShowWindow(handle, SW_SHOW);
IDK cokolwiek
źródło
1
[DllImport ("user32.dll")] zewnętrzny statyczny bool ShowWindow (IntPtr hWnd, int nCmdShow); [DllImport ("kernel32.dll")] zewnętrzne statyczne IntPtr GetConsoleWindow (); const int SW_HIDE = 0; const int SW_SHOW = 5;
soulmachine
1

Wiem, że nie odpowiadam dokładnie na to, czego chcesz, ale zastanawiam się, czy zadajesz właściwe pytanie.

Dlaczego nie użyjesz albo:

  1. usługa windows
  2. utwórz nowy wątek i uruchom na nim swój proces

Brzmi to jak lepsze opcje, jeśli chcesz tylko uruchomić proces.

Nathan Koop
źródło
3
Istnieje wiele scenariuszy, w których uruchomienie aplikacji konsoli narzędziowej jest całkowicie uzasadnione.
Adam Robinson
W moim przypadku oddzielny proces jest konieczny ze względu na model klient / serwer, z którego korzysta oprogramowanie, na którym pracuję.
Aaron Thomas
Utworzenie nowego wątku nie zawsze rozwiązuje problem. Są chwile, kiedy po prostu nie chcesz, aby denerwujące okno było w tle. Co więcej, jeśli masz process.start w pętli, nie wykonasz żadnej pracy, gdy okna konsoli pojawią się na twojej twarzy.
user890332
1
Uruchamiam aplikacje konsoli narzędziowej bez okien z Harmonogramu zadań. Nie ma potrzeby obsługi ani procesu nadrzędnego, z którego mógłby rozwidlić wątek. Te aplikacje zapisują do EventLog, jeśli potrzebne są dodatkowe dane wyjściowe.
subskrybuje
1

Chociaż, jak powiedziały inne odpowiedzi tutaj, możesz zmienić „Typ wyjścia” na „Aplikacja Windows”, pamiętaj, że oznacza to, że nie możesz używać, Console.Inponieważ stanie się NullStreamReader.

Console.Outi Console.Errorwydaje się, że nadal działa dobrze.

kjbartel
źródło
2
Mówisz poważnie? Po co ktoś miałby używać, Console.Ingdy nie ma konsoli do wprowadzania czegoś? Skąd powinno pochodzić coś, do czego można uzyskać dostęp przez Console.In? To w ogóle nie ma sensu. Innymi słowy: jest to całkowicie oczywiste i logiczne, że tak Console.Injest NullStreamReaderw tym przypadku.
Robert S.
1
@RobertS. Może fajka. To znaczy wyjście innego programu. To był mój przypadek użycia, kiedy to odkryłem.
kjbartel
1

W oparciu o powyższą odpowiedź Adama Markowitza, zadziałały dla mnie:

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();
Volcan Baru
źródło
1

Mam ogólne rozwiązanie do udostępnienia:

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);
        }
    }
}

Po prostu włącz tę klasę do swojego projektu i zadzwoń Magician.DisappearConsole();.

Konsola będzie migać po uruchomieniu programu poprzez jej kliknięcie. Podczas wykonywania z wiersza polecenia wiersz polecenia znika bardzo szybko po wykonaniu.

Robię to dla Discord Bota, który działa wiecznie w tle mojego komputera jako niewidoczny proces. To było łatwiejsze niż sprawienie, żeby TopShelf pracował dla mnie. Kilka samouczków TopShelf zawiodło mnie, zanim napisałem to z pomocą kodu, który znalazłem gdzie indziej. ; P

Próbowałem też po prostu zmienić ustawienia w Visual Studio> Projekt> Właściwości> Aplikacja, aby uruchomić jako aplikację systemu Windows zamiast aplikacji konsolowej, a coś w moim projekcie zapobiegło ukryciu mojej konsoli - być może dlatego, że DSharpPlus wymaga uruchomienia konsoli przy starcie . Nie wiem Bez względu na powód, ta klasa pozwala mi łatwo zabić konsolę po jej pojawieniu się.

Mam nadzieję, że ten Mag komuś pomoże. ;)

Lucas Jarrett
źródło
0

Tylko napisz

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

psi.CreateNoWindow = true;
Navin
źródło