Como mostro uma saída / janela do console em um aplicativo de formulários?

Para ficar preso imediatamente, um exemplo muito básico:

using System; using System.Windows.Forms; class test { static void Main() { Console.WriteLine("test"); MessageBox.Show("test"); } } 

Se eu compilar isso com opções padrão (usando csc na linha de comando), como esperado, ele será compilado para um aplicativo de console. Além disso, como importei o System.Windows.Forms , ele também mostrará uma checkbox de mensagem.

Agora, se eu usar o option /target:winexe , que eu acho que é o mesmo que escolher o Windows Application de dentro das opções do projeto, como esperado, só verei a Message Box e nenhuma saída do console.

(Na verdade, no momento em que é iniciado a partir da linha de comando, posso emitir o próximo comando antes que o aplicativo seja concluído).

Então, a minha pergunta é – eu sei que você pode ter “windows” / formulários de saída de um aplicativo de console, mas existe alguma maneira de mostrar o console de um aplicativo do Windows?

este deve funcionar.

 using System.Runtime.InteropServices; private void Form1_Load(object sender, EventArgs e) { AllocConsole(); } [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool AllocConsole(); 

Talvez isso seja simplista demais …

Crie um projeto do Windows Form …

Então: Propriedades do Projeto -> Aplicativo -> Tipo de Saída -> Aplicativo do Console

Em seguida, pode ter Console e formulários em execução juntos, funciona para mim

Se você não estiver preocupado em abrir um console no comando, poderá ir para as propriedades do seu projeto e alterá-lo para o Console Application.

captura de tela de alterar o tipo de projeto .

Isso ainda mostrará seu formulário, além de abrir uma janela do console. Você não pode fechar a janela do console, mas funciona como um excelente registrador temporário para debugging.

Lembre-se de desligá-lo antes de implantar o programa.

Você pode chamar AttachConsole usando o pinvoke para obter uma janela de console conectada a um projeto WinForms: http://www.csharp411.com/console-output-from-winforms-application/

Você também pode querer considerar o Log4net ( http://logging.apache.org/log4net/index.html ) para configurar a saída do log em diferentes configurações.

Isso funcionou para mim, canalizar a saída para um arquivo. Ligue para o console com

cmd / c “C: \ caminho \ para \ seu \ application.exe”> myfile.txt

Adicione este código ao seu aplicativo.

  [DllImport("kernel32.dll")] static extern bool AttachConsole(UInt32 dwProcessId); [DllImport("kernel32.dll")] private static extern bool GetFileInformationByHandle(SafeFileHandle hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation); [DllImport("kernel32.dll")] private static extern SafeFileHandle GetStdHandle(UInt32 nStdHandle); [DllImport("kernel32.dll")] private static extern bool SetStdHandle(UInt32 nStdHandle, SafeFileHandle hHandle); [DllImport("kernel32.dll")] private static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, SafeFileHandle hSourceHandle, IntPtr hTargetProcessHandle, out SafeFileHandle lpTargetHandle, UInt32 dwDesiredAccess, Boolean bInheritHandle, UInt32 dwOptions); private const UInt32 ATTACH_PARENT_PROCESS = 0xFFFFFFFF; private const UInt32 STD_OUTPUT_HANDLE = 0xFFFFFFF5; private const UInt32 STD_ERROR_HANDLE = 0xFFFFFFF4; private const UInt32 DUPLICATE_SAME_ACCESS = 2; struct BY_HANDLE_FILE_INFORMATION { public UInt32 FileAttributes; public System.Runtime.InteropServices.ComTypes.FILETIME CreationTime; public System.Runtime.InteropServices.ComTypes.FILETIME LastAccessTime; public System.Runtime.InteropServices.ComTypes.FILETIME LastWriteTime; public UInt32 VolumeSerialNumber; public UInt32 FileSizeHigh; public UInt32 FileSizeLow; public UInt32 NumberOfLinks; public UInt32 FileIndexHigh; public UInt32 FileIndexLow; } static void InitConsoleHandles() { SafeFileHandle hStdOut, hStdErr, hStdOutDup, hStdErrDup; BY_HANDLE_FILE_INFORMATION bhfi; hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); hStdErr = GetStdHandle(STD_ERROR_HANDLE); // Get current process handle IntPtr hProcess = Process.GetCurrentProcess().Handle; // Duplicate Stdout handle to save initial value DuplicateHandle(hProcess, hStdOut, hProcess, out hStdOutDup, 0, true, DUPLICATE_SAME_ACCESS); // Duplicate Stderr handle to save initial value DuplicateHandle(hProcess, hStdErr, hProcess, out hStdErrDup, 0, true, DUPLICATE_SAME_ACCESS); // Attach to console window – this may modify the standard handles AttachConsole(ATTACH_PARENT_PROCESS); // Adjust the standard handles if (GetFileInformationByHandle(GetStdHandle(STD_OUTPUT_HANDLE), out bhfi)) { SetStdHandle(STD_OUTPUT_HANDLE, hStdOutDup); } else { SetStdHandle(STD_OUTPUT_HANDLE, hStdOut); } if (GetFileInformationByHandle(GetStdHandle(STD_ERROR_HANDLE), out bhfi)) { SetStdHandle(STD_ERROR_HANDLE, hStdErrDup); } else { SetStdHandle(STD_ERROR_HANDLE, hStdErr); } } ///  /// The main entry point for the application. ///  [STAThread] static void Main(string[] args) { // initialize console handles InitConsoleHandles(); if (args.Length != 0) { if (args[0].Equals("waitfordebugger")) { MessageBox.Show("Attach the debugger now"); } if (args[0].Equals("version")) { String TypeOfBuild = ""; #if DEBUG TypeOfBuild = "d"; #else TypeOfBuild = "r"; #endif String output = TypeOfBuild + Assembly.GetExecutingAssembly().GetName().Version.ToString(); //Just for the fun of it Console.Write(output); Console.Beep(4000, 100); Console.Beep(2000, 100); Console.Beep(1000, 100); Console.Beep(8000, 100); return; } } } 

Eu encontrei este código aqui: http://www.csharp411.com/console-output-from-winforms-application/ Eu pensei que era digno de postá-lo aqui também.

Existem basicamente duas coisas que podem acontecer aqui.

Saída do console É possível que um programa winforms se conecte à janela do console que o criou (ou a uma janela de console diferente ou, na verdade, a uma nova janela do console, se desejado). Uma vez conectado à janela do console, o Console.WriteLine () etc funciona como esperado. Uma pegadinha dessa abordagem é que o programa retorna o controle para a janela do console imediatamente e, em seguida, continua escrevendo para ele, para que o usuário também possa digitar na janela do console. Você pode usar start com o parâmetro / wait para lidar com isso, eu acho.

Link para iniciar a syntax do comando

Saída de console redirecionada É quando alguém canaliza a saída do seu programa para outro lugar, por exemplo.

yourapp> arquivo.txt

Anexar a uma janela de console neste caso efetivamente ignora a tubulação. Para fazer esse trabalho, você pode chamar Console.OpenStandardOutput () para obter um identificador para o stream que a saída deve ser canalizada para. Isso só funciona se a saída for canalizada, portanto, se você quiser manipular ambos os cenários, será necessário abrir a saída padrão, gravar nela e append à janela do console. Isso significa que a saída é enviada para a janela do console e para o pipe, mas é a melhor solução que pude encontrar. Abaixo do código que eu uso para fazer isso.

 // This always writes to the parent console window and also to a redirected stdout if there is one. // It would be better to do the relevant thing (eg write to the redirected file if there is one, otherwise // write to the console) but it doesn't seem possible. public class GUIConsoleWriter : IConsoleWriter { [System.Runtime.InteropServices.DllImport("kernel32.dll")] private static extern bool AttachConsole(int dwProcessId); private const int ATTACH_PARENT_PROCESS = -1; StreamWriter _stdOutWriter; // this must be called early in the program public GUIConsoleWriter() { // this needs to happen before attachconsole. // If the output is not redirected we still get a valid stream but it doesn't appear to write anywhere // I guess it probably does write somewhere, but nowhere I can find out about var stdout = Console.OpenStandardOutput(); _stdOutWriter = new StreamWriter(stdout); _stdOutWriter.AutoFlush = true; AttachConsole(ATTACH_PARENT_PROCESS); } public void WriteLine(string line) { _stdOutWriter.WriteLine(line); Console.WriteLine(line); } } 
 using System; using System.Runtime.InteropServices; namespace SomeProject { class GuiRedirect { [DllImport("kernel32.dll", SetLastError = true)] private static extern bool AttachConsole(int dwProcessId); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetStdHandle(StandardHandle nStdHandle); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool SetStdHandle(StandardHandle nStdHandle, IntPtr handle); [DllImport("kernel32.dll", SetLastError = true)] private static extern FileType GetFileType(IntPtr handle); private enum StandardHandle : uint { Input = unchecked((uint)-10), Output = unchecked((uint)-11), Error = unchecked((uint)-12) } private enum FileType : uint { Unknown = 0x0000, Disk = 0x0001, Char = 0x0002, Pipe = 0x0003 } private static bool IsRedirected(IntPtr handle) { FileType fileType = GetFileType(handle); return (fileType == FileType.Disk) || (fileType == FileType.Pipe); } public static void Redirect() { if (IsRedirected(GetStdHandle(StandardHandle.Output))) { var initialiseOut = Console.Out; } bool errorRedirected = IsRedirected(GetStdHandle(StandardHandle.Error)); if (errorRedirected) { var initialiseError = Console.Error; } AttachConsole(-1); if (!errorRedirected) SetStdHandle(StandardHandle.Error, GetStdHandle(StandardHandle.Output)); } } 
 //From your application set the Console to write to your RichTextkBox //object: Console.SetOut(new RichTextBoxWriter(yourRichTextBox)); //To ensure that your RichTextBox object is scrolled down when its text is //changed add this event: private void yourRichTextBox_TextChanged(object sender, EventArgs e) { yourRichTextBox.SelectionStart = yourRichTextBox.Text.Length; yourRichTextBox.ScrollToCaret(); } public delegate void StringArgReturningVoidDelegate(string text); public class RichTextBoxWriter : TextWriter { private readonly RichTextBox _richTextBox; public RichTextBoxWriter(RichTextBox richTexttbox) { _richTextBox = richTexttbox; } public override void Write(char value) { SetText(value.ToString()); } public override void Write(string value) { SetText(value); } public override void WriteLine(char value) { SetText(value + Environment.NewLine); } public override void WriteLine(string value) { SetText(value + Environment.NewLine); } public override Encoding Encoding => Encoding.ASCII; //Write to your UI object in thread safe way: private void SetText(string text) { // InvokeRequired required compares the thread ID of the // calling thread to the thread ID of the creating thread. // If these threads are different, it returns true. if (_richTextBox.InvokeRequired) { var d = new StringArgReturningVoidDelegate(SetText); _richTextBox.Invoke(d, text); } else { _richTextBox.Text += text; } } } 

Você pode alternar a qualquer momento entre o tipo de aplicativos, o console ou o Windows. Então, você não irá escrever uma lógica especial para ver o stdout. Além disso, ao executar o aplicativo no depurador, você verá todos os stdout na janela de saída. Você também pode simplesmente adicionar um ponto de interrupção e, em propriedades de ponto de interrupção, alterar “Quando Acertar …”, você pode gerar quaisquer mensagens e variables. Além disso, você pode marcar / desmarcar “Continuar execução” e seu ponto de interrupção se tornará em formato quadrado. Portanto, as mensagens de ponto de interrupção sem alterar nada no aplicativo na janela de saída de debugging.