Como executar um aplicativo de console C # com o console oculto

141

Existe uma maneira de ocultar a janela do console ao executar um aplicativo de console?

Atualmente, estou usando um aplicativo Windows Forms para iniciar um processo do console, mas não quero que a janela do console seja exibida enquanto a tarefa estiver em execução.

Aaron Thomas
fonte
tente executar o aplicativo de console da tarefa agendada.

Respostas:

158

Se você estiver usando a ProcessStartInfoclasse, poderá definir o estilo da janela como oculto - no caso de aplicativos de console (não GUI), será necessário configurar o CreateNoWindow para 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
fonte
26
Apenas o que eu estava indo para pós :)
Jon Skeet
75
Caramba - alguém mais rápido que Jon! =)
Erik Forbes
75
Eu tive que estrangular sua conexão com a internet para vencê-lo;)
Adam Markowitz
11
Não funcionou para chamar uma ferramenta de linha de comando. Usado yourprocess.StartInfo.CreateNoWindow = true; em vez disso, veja abaixo.
Christian
12
Não oculta a janela do console, é necessário StartInfo.CreateNoWindow = true.
Daniel
201

Se você escreveu o aplicativo de console, pode ocultá-lo por padrão.

Crie um novo aplicativo de console e altere o tipo "Tipo de saída" para "Aplicativo do Windows" (feito nas propriedades do projeto)

Simon
fonte
6
Eu estava tentando ocultar meu próprio console, não chamar outra coisa e depois ocultá-lo (como a resposta aceita) - então esse foi o melhor para mim. obrigado!
21912 Imserious #
6
Obrigado parceiro ! Isto é o que eu estava procurando também!
Varun Sharma
3
A resposta aceita supõe isso porque está declarada na pergunta.
Aqua
mais simples way..really gostava it..we certamente não quer mostrar a janela beacuse vai lançar outro processo a partir dele para mim ..
Sai Avinash
1
Este contorna problemas com o ProcessStartInfo, onde você especifica credenciais do usuário e esse usuário está logado ou atual. Nessa situação, a propriedade CreateNoWindow é ignorada para que você sempre obtenha uma janela do console. Ao definir o aplicativo do console como Aplicativo do Windows, mas sem uma janela, você não obtém nenhuma janela.
tjmoore
67

Se você estiver usando Process Class, poderá escrever

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

antes yourprocess.start();e o processo ficará oculto

Peter Mortensen
fonte
4
Boa sorte se você precisar interromper esse processo mais cedo. Process.Kill termina abruptamente. Process.CloseMainWindow falha. GenerateConsoleCtrlEvent falha ao enviar ctrl + c ou ctrl + break para o processo. WM_CLOSE para todas as janelas de encadeamento no processo falha. Parece não haver maneira de terminar de forma limpa um processo iniciado com esses dois valores de parâmetro. Veja minha pergunta aqui: stackoverflow.com/questions/16139571/…
Triynko
Graças toneladas, este foi o mais simples. Além disso, se você possui (ou dept) o código do console, achei este exemplo de mutex o mais fácil para um desligamento limpo. stackoverflow.com/a/31586184/1877412
cbuteau 21/01
1
@Triynko: Você não pode terminar de forma limpa nenhum processo, a menos que esse processo coopere ativamente. Não se trata de bandeiras ou qualquer outra coisa. Não há nada no sistema operacional que possa desencadear um desligamento limpo. A solução comum aqui é usar um objeto de kernel aguardável, sinalizado no processo de controle, quando o processo escravo deve terminar. O processo escravo precisa monitorar ativamente o estado desse objeto que pode ser aguardado e iniciar o desligamento limpo depois de sinalizado.
imprevisível em 20/08
43

A resposta simples é: Acesse as propriedades do aplicativo do console (propriedades do projeto). Na guia "Aplicativo", altere o "Tipo de saída" para "Aplicativo do Windows". Isso é tudo.

Cihan
fonte
4
Alvo. É o mesmo que criar um aplicativo do Windows que não chama nenhum formulário.
ashes999
1
Essa é a resposta correta. Nenhuma de suas outras abordagens bandaid. Esta é a resposta correta. Você deseja que seu aplicativo nunca abra um console em primeiro lugar. Além disso, você deseja abrir um formulário a qualquer momento. Então basta ligar para o formulário quando quiser. ou seja, nosso formulário é chamado quando o usuário clica com o botão direito do mouse no ícone da bandeja do sistema e seleciona preferências. ESTA É A RESPOSTA CERTA!!!
Bluebaron
20

Você pode usar a API do FreeConsole para desanexar o console do processo:

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

(é claro que isso é aplicável apenas se você tiver acesso ao código fonte do aplicativo do console)

Thomas Levesque
fonte
Eu queria não mostrar o console. Enquanto FreeConsolefaz o que o nome diz, ele não impede o Windows de exibir o console antes de ser chamado.
Jader Dias
5
Em seguida, compilar o projeto como um aplicativo do Windows, não um aplicativo do console
Thomas Levesque
1
Para o registro, é exatamente isso que eu precisava, obrigado. Também é exatamente o que o título pede :) Portanto, no interesse de outros viajantes do Google, +1
veja
3
Além disso [DllImport("kernel32.dll")] static extern bool AllocConsole();permite que você facilmente executar com um console a partir de um padrão Win32 aplicativo
sehe
1
Funciona para o meu aplicativo .NET Core 2.2 - se alguém estiver procurando isso especificamente.
Medismal 25/08/19
7

Se você estiver interessado na saída, pode usar esta função:

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

Ele executa o programa de linha de comando especificado, aguarda o término e retorna a saída como string.

JCH2k
fonte
4

Se você estiver criando um programa que não exija entrada do usuário, sempre poderá criá-lo como um serviço. Um serviço não mostra nenhum tipo de interface do usuário.

Chris Bregg
fonte
Mas se tudo o que você deseja fazer é executar o processo até que ele saia, por exemplo, chamando-o do Agendador de tarefas, um serviço é inconveniente, pois continua a existir. Em algumas situações, alterar o Tipo de saída para Aplicativo do Windows versus o ProcessWindowStyle alternativo como oculto é muito conveniente.
subsci
2

Adicione isso à sua classe para importar o arquivo 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;

E então, se você deseja ocultá-lo, use este comando:

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

E se você quiser mostrar o console:

var handle = GetConsoleWindow();
ShowWindow(handle, SW_SHOW);
IDK qualquer coisa
fonte
1
[DllImport ("user32.dll")] estático externo ShowWindow (IntPtr hWnd, int nCmdShow); [DllImport ("kernel32.dll")] estático externo IntPtr GetConsoleWindow (); const int SW_HIDE = 0; const int SW_SHOW = 5;
soulmachine
1

Sei que não estou respondendo exatamente o que você deseja, mas estou me perguntando se você está fazendo a pergunta certa.

Por que você também não usa:

  1. serviço do windows
  2. crie um novo encadeamento e execute seu processo nesse

Essas opções parecem melhores se tudo o que você quer é executar um processo.

Nathan Koop
fonte
3
Existem muitos cenários em que o lançamento de um aplicativo de console utilitário é perfeitamente legítimo.
9119 Adam Robinson
No meu caso, é necessário um processo separado devido ao modelo cliente / servidor usado pelo software em que estou trabalhando.
Aaron Thomas
Nem sempre resolve o problema para criar um novo thread. Há momentos em que você simplesmente não deseja a janela irritante em segundo plano. Além disso, e se você tiver um process.start em um loop, não executará nenhum trabalho quando as janelas do console aparecerem na sua cara.
user890332
1
Inicio aplicativos do console utilitário sem janelas a partir do Agendador de tarefas. Não há necessidade de serviço nem processo pai a partir do qual bifurcar um encadeamento. Esses aplicativos gravam no EventLog se for necessária uma saída adicional.
subsci
1

Embora, como outras respostas aqui tenham dito, você possa alterar o "Tipo de saída" para "Aplicativo do Windows", saiba que isso significa que você não pode usá- Console.Inlo, pois ele se tornará um NullStreamReader.

Console.Oute Console.Errorparece ainda funcionar bem no entanto.

kjbartel
fonte
2
Você está falando sério? Por que alguém usaria Console.Inquando não há console para inserir algo? De onde deve vir algo que possa ser acessado Console.In? Isso não faz nenhum sentido. Em outras palavras: é totalmente óbvio e lógico que Console.Iné um NullStreamReaderneste caso.
Robert S.
1
@RobertS. Um cachimbo talvez. Ou seja, a saída de outro programa. Esse foi o meu caso de uso quando descobri isso.
kjbartel
1

Com base na resposta de Adam Markowitz acima, o seguinte funcionou para mim:

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
fonte
1

Eu tenho uma solução geral para compartilhar:

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

Basta incluir esta classe no seu projeto e ligar Magician.DisappearConsole();.

Um console piscará quando você iniciar o programa clicando nele. Ao executar no prompt de comando, o prompt de comando desaparece logo após a execução.

Eu faço isso para um Discord Bot que roda para sempre no fundo do meu computador como um processo invisível. Era mais fácil do que fazer o TopShelf trabalhar para mim. Alguns tutoriais do TopShelf falharam antes de eu escrever isso com alguma ajuda do código que encontrei em outro lugar. ; P

Eu também tentei simplesmente alterar as configurações no Visual Studio> Projeto> Propriedades> Aplicativo para iniciar como um aplicativo do Windows em vez de um aplicativo de console, e algo sobre o meu projeto impediu que isso ocultasse meu console - talvez porque o DSharpPlus exija iniciar um console na inicialização . Eu não sei. Seja qual for o motivo, essa classe me permite matar facilmente o console depois que ele aparece.

Espero que este mago ajude alguém. ;)

Lucas Jarrett
fonte
0

Apenas escreva

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

psi.CreateNoWindow = true;
Navin
fonte