Как показать консольный вывод/окно в приложении форм?
Чтобы застрять сразу, очень простой пример:
using System;
using System.Windows.Forms;
class test
{
static void Main()
{
Console.WriteLine("test");
MessageBox.Show("test");
}
}
Если я скомпилирую это с настройками по умолчанию (используя csc в командной строке), как и ожидалось, он будет компилироваться в консольное приложение. Кроме того, поскольку я импортировал System.Windows.Forms
, он также отобразит окно сообщения.
Теперь, если я использую опцию /target:winexe
, которая, как я думаю, такая же, как выбор Windows Application
из параметров проекта, как ожидается, я увижу только окно сообщения и никакой вывод консоли.
(Фактически, момент, когда он запускается из командной строки, я могу выполнить следующую команду до того, как приложение даже завершится).
Итак, мой вопрос: я знаю, что вы можете иметь "окна" /формы вывода из консольного приложения, но есть ли все-таки показать консоль из приложения Windows?
Ответы
Ответ 1
это должно работать.
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();
Ответ 2
Возможно, это слишком упрощенное...
Создайте проект Windows Form...
Затем: Свойства проекта → Приложение → Тип вывода → Консольное приложение
Затем может работать Консоль и Формы, работает для меня
Ответ 3
Если вы не беспокоитесь об открытии консоли по команде, вы можете перейти в свойства своего проекта и изменить его на Консольное приложение
.
Это все еще покажет вашу форму, а также всплывет окно консоли. Вы не можете закрыть окно консоли, но оно отлично работает как временный регистратор для отладки.
Просто не забудьте отключить его перед развертыванием программы.
Ответ 4
Вы можете вызвать AttachConsole
с помощью pinvoke, чтобы получить окно консоли, подключенное к проекту WinForms: http://www.csharp411.com/console-output-from-winforms-application/
Вы также можете рассмотреть Log4net (http://logging.apache.org/log4net/index.html) для настройки вывода журнала в разных конфигурациях.
Ответ 5
Это сработало для меня, чтобы направить вывод в файл.
Вызовите консоль с помощью
cmd/c "C:\path\to\your\application.exe" > myfile.txt
Добавьте этот код в свое приложение.
[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);
}
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[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"))
{
#if DEBUG
String typeOfBuild = "d";
#else
String 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;
}
}
}
Я нашел этот код здесь: http://www.csharp411.com/console-output-from-winforms-application/
Я думал, что было бы достойно опубликовать это здесь.
Ответ 6
В основном есть две вещи, которые могут произойти здесь.
Консольный выход
Программа winforms может присоединяться к окну консоли, который ее создал (или к другому окну консоли или, если необходимо, к новому окну консоли). После подключения к консольному окну Console.WriteLine() и т.д. Работает так, как ожидалось. Одна из них заключается в том, что программа немедленно возвращает управление в консольное окно, а затем продолжает записывать на нее, поэтому пользователь может также ввести в консольное окно. Вы можете использовать start с параметром /wait для обработки этого, я думаю.
Ссылка на начало синтаксиса команд
Перенаправленный вывод консоли
Это когда кто-то передает данные из вашей программы в другое место, например.
yourapp > file.txt
Прикрепление к консольному окну в этом случае эффективно игнорирует трубопровод. Чтобы выполнить эту работу, вы можете вызвать Console.OpenStandardOutput(), чтобы получить дескриптор потока, к которому должен быть подключен вывод. Это работает только в том случае, если вывод передан по каналам, поэтому, если вы хотите обрабатывать оба сценария, вам нужно открыть стандартный вывод и записать на него и прикрепить к консольному окну. Это означает, что вывод отправляется в окно консоли и в трубку, но это лучшее решение, которое я могу найти. Ниже кода, который я использую для этого.
// 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);
}
}
Ответ 7
Вы можете создать приложение Windows Forms и изменить тип вывода на Console.
В результате откроется как консоль, так и форма.
![enter image description here]()
Ответ 8
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));
}
}
Ответ 9
//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;
}
}
}
Ответ 10
Я думаю, что то, что вы ищете, называется piping, где IO доступно как поток для любого другого приложения. Это позволит пользователю передать команду и вернуть ее обратно в текстовое поле. Это то, что написал год назад для достижения того же:
public static void ExecPro(string ProcessName, string args, string WrkDir, string cmdtxt, out string coutext)
{
Process cmd = new Process();
cmd.StartInfo.FileName = ProcessName;
cmd.StartInfo.Arguments = args;
cmd.StartInfo.UseShellExecute = false;
cmd.StartInfo.WorkingDirectory = WrkDir;
cmd.StartInfo.CreateNoWindow = true;
cmd.StartInfo.ErrorDialog = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardError = true;
cmd.Start();
StreamWriter cin = cmd.StandardInput;
StreamReader cout = cmd.StandardOutput;
cin.WriteLine(cmdtxt);
cin.Close();
coutext = cout.ReadToEnd();
cmd.WaitForExit();
cmd.Close();
}
Ответ 11
Вы можете в любое время переключаться между типами приложений, консолями или окнами. Таким образом, вы не будете писать специальную логику, чтобы увидеть stdout. Кроме того, при запуске приложения в отладчике вы увидите все stdout в окне вывода. Вы также можете просто добавить точку останова, а в свойствах точки останова "When Hit..." вы можете выводить любые сообщения и переменные. Также вы можете проверить/снять флажок "Продолжить выполнение", и ваша точка останова станет квадратной. Таким образом, сообщения точки останова без изменения чего-либо в приложении в окне вывода отладки.
Ответ 12
Почему бы просто не оставить его как приложение Window Forms и создать простую форму, имитирующую консоль. Форма может выглядеть так же, как консоль с черным экраном, и она может реагировать непосредственно на нажатие клавиши.
Затем в файле program.cs вы решаете, нужно ли запускать основную форму или ConsoleForm. Например, я использую этот подход для захвата аргументов командной строки в файле program.cs. Я создаю ConsoleForm, сначала скрываю его, затем передаю строки командной строки в функцию AddCommand, которая отображает разрешенные команды. Наконец, если пользователь дал -h или -? Команда, я вызываю .Show на ConsoleForm, и когда пользователь нажимает любую клавишу на нем, я закрываю программу. Если пользователь не дает -? По команде закрываю скрытую ConsoleForm и запускаю основную форму.