- Как отобразить вывод/окно консоли в приложении forms?
- 9 ответов:
- Вызов консоли в WinForm приложении
- Решение
- Решение
- C# 411
- About C# 411
- C# Information
- Subscribe C# 411
- Links
- Information
- Console Output from a WinForms Application
- Simple Example
- One Gotcha
- Comments
- 45 Responses to “Console Output from a WinForms Application”
Как отобразить вывод/окно консоли в приложении forms?
застрять сразу, очень простой пример:
если я скомпилирую это с параметрами по умолчанию (используя csc в командной строке), как и ожидалось, он будет компилироваться в консольное приложение. Кроме того, потому что я импортировал System.Windows.Forms , Он также покажет окно сообщения.
теперь, если я использую опцию /target:winexe Я думаю, что это то же самое, что Windows Application из параметров проекта, как и ожидалось, я буду видеть только окно сообщения и не выводить консоль.
(In факт, в тот момент, когда он запускается из командной строки, я могу выдать следующую команду, прежде чем приложение даже завершится).
Итак, мой вопрос — я знаю, что вы можете иметь вывод «windows»/forms из консольного приложения, но есть ли в любом случае, чтобы показать консоль из приложения Windows?
9 ответов:
создать проект Windows Form.
Затем: Свойства Проекта — > Приложение — > Тип Вывода — > Консольное Приложение
тогда может иметь консоль и формы, работающие вместе, работает для меня
Если вы не беспокоитесь об открытии консоли по команде, вы можете перейти в свойства для вашего проекта и изменить его на консольное приложение
Это будет по-прежнему показывать вашу форму, а также выскакивает окно консоли. Вы не можете закрыть окно консоли, но он работает как отличный временный регистратор для отладки.
просто не забудьте выключить его перед развертыванием программы.
можно назвать AttachConsole использование pinvoke для подключения окна консоли к проекту WinForms:http://www.csharp411.com/console-output-from-winforms-application/
вы также можете рассмотреть Log4net ( http://logging.apache.org/log4net/index.html) для настройки вывода журнала в различных конфигурациях.
это сработало для меня, чтобы передать вывод в файл. Вызовите консоль с помощью
cmd /c «C:\path\to\your\application.exe » > myfile.txt
добавьте этот код в приложение.
есть в основном две вещи, которые могут произойти здесь.
вывод на консоль Программа winforms может присоединяться к создавшему ее консольному окну (или к другому консольному окну, или даже к новому консольному окну, если это необходимо). После подключения к консоли окна консоли.WriteLine () etc работает так, как ожидалось. Один из них заключается в том, что программа немедленно возвращает управление в окно консоли, а затем продолжает писать в него, поэтому пользователь может также введите в окне консоли. Вы можете использовать start с параметром /wait, чтобы справиться с этим, я думаю.
перенаправление вывода консоли Это когда кто-то передает вывод из вашей программы куда-то еще, например.
прикрепление к окну консоли в этом случае эффективно игнорирует трубопроводы. Чтобы сделать эту работу вы можете вызвать консоль.OpenStandardOutput() для получения дескриптора поток, в который должен передаваться вывод. Это работает только в том случае, если вывод передается по конвейеру, поэтому, если вы хотите обработать оба сценария, вам нужно открыть стандартный вывод и записать его и прикрепить к окну консоли. Это означает, что вывод отправляется в окно консоли и в трубу, но это лучшее решение, которое я мог найти. Ниже код, который я использую для этого.
Вызов консоли в WinForm приложении
Как переделать с консоли на WinForm?
Первое слово в строке перевести в верхний регистр(большие буквы), как это реализовать в WinForm .
Вызов форм из консоли
Здравствуйте, уже неделю пытаюсь решить задачу, но пока результатов мало.. Задание: вызвать из.
Вызов консоли с winforms
мне нужно ввести несколько параметров с консоли в проекте winforms, но после первого ввода выдает.
Вызов из консоли системы
Добрый день всем. Скажу сразу — я любитель. C# — мое хобби что ли. Вопрос: Есть форма.
конечно реально. Какую именно консоль?
если просто консольное приложение надо:
Обычную консоль, как в консольном приложении.
Например ,что-бы считать данные можно было так :
как вызвать я написал, а как обеспечить синхронизацию ,сам придумай. Варианты есть разные.
Можешь через временный фаил.
Вот ещё почитай, хотя там тоже самое что я написал.
Запуск консольного приложения из WindowsForm
или ты как объект(класс объявить) хочешь в винформсе создать консль?
Именно это и хочу .
Идея в следующем :
Есть основная форма . В определенный момент она должна открыть консоль и считать оттуда введенные данные .
Решение
Решение
Спасибо огромное ,именно то что нужно было.
В Шилдте или Троелсене такого вроде нет.
И вопрос — когда создается консольное приложение то тоже импортируется эта библиотека?
где вы инфу по таким вещам берете? Имею в виду:
Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь или здесь.
Вызов winform из unity
Как из юнити приложения вызвать винформ? просто подключить using System.Windows.Forms; а затем.
Вывод консоли в оконном приложении
Мне нужно затестировать как работает функция, т.е. выводить каждую операцию. Что — то.
Вызов функции в .NET-приложении
Нужно решить не особо сложную задачу из умножения матриц. Решил использовать для этой цели matlab.
Вызов действия в стороннем приложении
можно ли как-то вызвать действие чтобы файл его выполил?
C# 411
About C# 411
C# Information
Subscribe C# 411
Links
Information
Console Output from a WinForms Application
You may wish to enable your WinForms application to run from a console window or command line. And when it does, you probably want to send output messages to the console window that launched your WinForms application.
Unfortunately Console.WriteLine()–the standard method of writing to the console window–by default will not work from a WinForms application. That’s because the console window that launched your WinForms application belongs to the cmd.exe process, which is separate from your WinForms application process.
So to redirect output from a WinForms application to the console window that launched it, use the AttachConsole Win32 method introduced in Windows XP. AttachConsole attaches the current process to the console window of another process. The special parameter ATTACH_PARENT_PROCESS attaches to the parent process, which in this case is the console window that launched the WinForms application.
Simple Example
Following is a simple WinForms application that redirects its output to the console window that launched it:
One Gotcha
There is one problem with this approach. If you redirect the console window output to a text file, for example using the redirect arrow:
MyWinFormsApp.exe >output.txt arg1 arg2
In this case, output will not redirect to the “output.txt” text file as expected, but instead will continue to appear in the console window. Please comment if you have a solution to this issue.
Comments
45 Responses to “Console Output from a WinForms Application”
Thanks for the how-to, it really helped me out. I haven’t found a solution to your gotcha, but I have another gotcha to tack on.
While this solution successfully redirects output to the console, it doesn’t seem to “grab” the console’s full attention. That is to say, as soon as my application has loaded, the console drops down and represents the command prompt. Even as output is being printed out from my program to the console, I can navigate folders, run other applications, etc. from the same instance of cmd.exe. For my purposes, this isn’t a huge deal, just something I noticed.
Thanks again for the post.
Though the reason is not palpable, but the solution works…
Hello!
I think this try.
Microsoft sux… how can this not be standard??
Does this change the prompt style if you run it from a cmd.exe window? It might be something else I’m doing, that I only noticed after finding your (very helpful!) tutorial…?
I noticed the same behavior as well. I also noticed that my application doesn’t properly exit. The enter key must be pressed ey before the application will exit.
Though I thank and commend the writer for his efforts, I cannot honestly say that this was “nicely done” as some others have stated.
There has to be another way to achieve console output from a C# Windows Application. I’ll find it :o)
you don’t have to press any key to exit the app. It’s just that console output of WinForms apps isn’t handled synchronously by the Windows command processor cmd.exe. So cmd.exe will print its own user prompt (“C:whatever>”) before the console output of the WinForms app. On my machine, it looks like this:
C:test>MyWinFormsApp.exe
C:test>
You specified 0 arguments:
_ start “” /WAIT MyWinFormsApp.exe
or
C:test>cmd /c MyWinFormsApp.exe
Sorry, my last post what somehow messed up at the end. I’ll try again:
…
On my machine, it looks like this:
C:test>MyWinFormsApp.exe
C:test>
You specified 0 arguments:
_ <=cursor blinks here
So while it may look like the app isn’t finished yet, it actually is. Try entering “dir”, and you’ll see.
To make cmd.exe wait for the WinFormsApp to finish, try:
C:test>start “” /WAIT MyWinFormsApp.exe
or
C:test>cmd /c MyWinFormsApp.exe
I might have found a solution to your “gotcha”. It involves duplicating the original Stdout / Stderr handles before calling “AttachConsole()” and resetting them afterwards.
static class Program
<
[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);
>
>
[STAThread]
static void Main(string[] args)
<
// initialize console handles
InitConsoleHandles();
// to demonstrate where the console output is going
int argCount = args == null ? 0 : args.Length;
Console.WriteLine(“You specified <0>arguments:”, argCount);
Console.Error.WriteLine(“This is the error channel”);
for (int i = 0; i brammam on August 4th, 2009 at 4:19 am
Hi Hartmut Honisch,
This is working greatly in my test application. after i add it in to my original application it is not working. why its behaving like this working in one application, not working in another.
First off, great post thanks, it has helped a lot so far.
Hopefully it is not so old, as to have died! In response to the post by Hartmut Honisch, I have a quick question/favour to ask.
Do you have any solutions to the problem posted by CupOfJoe, where as the enter key must be pressed before the application will exit?
I have one potential solution which is to use:
after you have finished with your app/printing to the console. However this adds in an extra line if you output via batch or stream to file.
eg: C:>myapp.exe -help > dump.txt
will give an output of
So as a solution, do you know if we could detect if the app was run via batch or the commandline, or if it streamed (piped?) to the console or file?
Then we could trigger if the System.Windowns.Forms.SendKeys.SendWait(“
Any ideas would be great.
Here is my sample program.cs file.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace ConsoleOutTesting
<
static class Program
<
#region Stuff used to attach a command window to the win forms exe
[DllImport(«kernel32.dll»)]
static extern bool AttachConsole(UInt32 dwProcessId);
[DllImport(«kernel32.dll»)]
static extern bool FreeConsole();
[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;
static SafeFileHandle hStdOut, hStdErr, hStdOutDup, hStdErrDup;
static BY_HANDLE_FILE_INFORMATION bhfi;
private 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;
>
private static void InitConsoleHandles()
<
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);
>
private static void ReleaseConsoleHandles()
<
SendKeys.SendWait(«
///
/// The main entry point for the application.
///
[STAThread]
static void Main(string[] args)
<
if (args.Length == 1 && args[0] == «-help»)
<
InitConsoleHandles();
Console.WriteLine(«MyApp help is this»);
ReleaseConsoleHandles();
>
else
<
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
>
>
>
>
Jonathan, this is the code I’m using to know if the app is run from cmd.exe:
char Title[MAX_PATH] = “”;
if(GetConsoleTitle(Title, MAX_PATH) &&
strcmp(&Title[strlen(Title) – 7], “cmd.exe”) == 0)
<
// Launch by cmd.exe
>
You might want to add some protection:
char Title[MAX_PATH] = “”;
if(GetConsoleTitle(Title, MAX_PATH) && strlen(Title) >= 7 && strcmp(&Title[strlen(Title) – 7], “cmd.exe”) != 0)
<
// Launched by cmd.exe
>
Thanks Crayon for your post. I have modified what you have posted to fit my situation but unfortunately I can’t seem to get GetConsoleTitle to work! The error code I get is 183, “Cannot create a file when that file already exists.” and I have no idea why! The string builder comes back empty.
I have followed this post http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=109 to use the GetConsoleTitle, but I can’t seem to get it to work.
My code for the main function is currently this:
StringBuilder sb = new StringBuilder(1000000);
UInt32 buffSize = (UInt32)sb.Capacity;
UInt32 titleLen = GetConsoleTitle(sb, buffSize);
Console.WriteLine(“MyApp help is this”);
ReleaseConsoleHandles();
>
else
<
Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
>
Any ideas? Thanks.
Jonathan, in my code I’m calling GetConsoleTitle after
AttachConsole(ATTACH_PARENT_PROCESS).
For the rest, I can’t really help you. I never programmed in .NET. That’s why the code pasted above is in C/C++.
Hi Crayon, Thanks, I tried putting GetConsoleTitle after the AttachConsole call, but no luck so far, still the same error.
I’ll keep looking for an answer and post it here if I find one.
This seems to work well for my needs. Greatly appreciated.
You are simply a genius da.
If you attach the Standard input with the output and error then you won’t have to use the sendkeys command and it will fix the issue with not grabbing the attention of the entire console. I edited the code posted above to the following:
[DllImport(“kernel32.dll”)]
static extern bool AttachConsole(UInt32 dwProcessId);
[DllImport(“kernel32.dll”)]
static extern bool FreeConsole();
[DllImport(“kernel32.dll”)]
static extern bool AllocConsole();
[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_INPUT_HANDLE = 0xFFFFFFF6;
private const UInt32 STD_OUTPUT_HANDLE = 0xFFFFFFF5;
private const UInt32 STD_ERROR_HANDLE = 0xFFFFFFF4;
private const UInt32 DUPLICATE_SAME_ACCESS = 2;
static SafeFileHandle hStdIn, hStdOut, hStdErr, hStdOutDup, hStdErrDup, hStdInDup;
static BY_HANDLE_FILE_INFORMATION bhfi;
private 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;
>
private static void InitConsoleHandles()
<
hStdIn = GetStdHandle(STD_INPUT_HANDLE);
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, hStdIn, hProcess, out hStdInDup, 0, true, DUPLICATE_SAME_ACCESS);
// 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);
//AllocConsole();
// Adjust the standard handles
if (GetFileInformationByHandle(GetStdHandle(STD_INPUT_HANDLE), out bhfi))
<
SetStdHandle(STD_INPUT_HANDLE, hStdInDup);
>
else
<
SetStdHandle(STD_INPUT_HANDLE, hStdIn);
>
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);
>
>
private static void ReleaseConsoleHandles()
<
FreeConsole();
>
Hi all,
I have developed a C# Windows application and I need to add command line support for it. Using the AttachConsole method I succeeded to output messages from the application to the console window that launched the application.
The problem is that the console also prints the user prompt (“C:[path]>”) before the apllication messages are printed.
Is there any way to avoid printing the user prompt? I just want to output my messages from the Windows application directly to the cursor location.
Just an FYI, this may not be a huge concern, I’ve noticed that when ran from a batch file, this solution works well which was the point of me adding cmd line functionality, so I’m happy, although obviously I still want “perfect” 🙂
Perfect – just what I needed! (I don’t mind the dumping to txt file issue)
reverse it create a winform app,
process commandline arguments and specify in the properties of you project that it is a console app.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Text;
namespace QDB
<
static class Program
<
///
/// The main entry point for the application.
///
[STAThread]
static void Main(string[] args)
<
bool NoGui = false;
string name = “”;
int number = 0;
for (int i = 0; i != args.Length; ++i)
<
switch (args[i])
<
case “/NoGui”: NoGui = true; break;
case “/name” : name = args[++i]; break;
case “/number”: number = int.Parse(args[++i]); break;
default: Console.WriteLine(“Invalid args!”); return;
>
if (!NoGui)
<
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmAppMain());
>
else
<
foreach (string arg in args)
<
Console.WriteLine(” the vars: <0>”, arg);
>
Console.ReadLine();
Many thanks to winform,Hartmut Honisch,Jonathan Counihan and of course Timm.
I combined your logic and code…Below is what you wanted!
Test Run:-
1)d:>ConsoleTest.exe
RESULT:- Opens up only GUI.
RESULT:- Opens up only Console.
3)d:>ConsoleTest.exe /NoGui 1>a.txt 2>b.txt
RESULT:- Opens up only Console. It redirect standard output to a.txt and standard error to b.txt
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.Win32.SafeHandles;
using System.Diagnostics;
namespace ConsoleTest
<
static class Program
<
[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)
<
bool NoGui = false;
string name = “”;
int number = 0;
for (int i = 0; i != args.Length; ++i)
<
switch (args[i])
<
case “/NoGui”: NoGui = true; break;
case “/name”: name = args[++i]; break;
case “/number”: number = int.Parse(args[++i]); break;
default: Console.WriteLine(“Invalid args!”); return;
>
if (!NoGui)
<
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
>
else
<
// initialize console handles
InitConsoleHandles();
// to demonstrate where the console output is going
int argCount = args == null ? 0 : args.Length;
Console.WriteLine(“nnn************Console Application Starting. *************”);
Console.WriteLine(“You specified <0>arguments:”, argCount);
Console.Error.WriteLine(“This is the error channel”);
for (int i = 0; i NizZ8 on November 18th, 2010 at 10:09 pm
Thanks for posting this (and great comments)!
Got a better solution:
Right click the project and select “Property”, in the Application tab, you can see “Output Type:” is “Windows Application” in default for Form application. Change it to Console Application, there is no modification needed in your source code. All problem solved. The output can be redirected to text file, and the command prompt is not messed up.
@Ben: Yeah, except it’s no longer a WinForms application when you change it to Console Application.
Ben, I like your solution with one reservation that unfortunately makes it unusable for me.
After changing the application property “Output Type” from “Windows Application” to “Console Application” the application still functions as a Windows Application. Starting it as a console application gives the usual console application capabilities such as console output and I/O redirection.
The unfortunate part is that, when running as a Windows Application a console window is automatically opened (which disappears when the Windows Application is closed). Does anyone know a way to inhibit display of the console window?
@Jeff
If you call AttachConsole( ATTACH_PARENT_PROCESS ) then it “shouldn’t” open up a new window. AllocConsole always does, though. I think.
Hi Jeff, my final solution is to FreeConsole if the console is not needed. Please check my post for details:
http://benincampus.blogspot.com/2011/03/re-console-output-from-winforms.html
I like the simplicity of Ben’s solution, however, the flashing console window is annoying. So I still like the I/O redirection approach above better.
Additionally, I found that this line is not really necessary. My program exits properly w/o waiting for an Enter.
System.Windows.Forms.SendKeys.SendWait(“
Sorry, please ignore my comment regarding the SendWait line!
It’s not needed when the application’s output type is “Console Application”, but it IS needed when the type is “Windows Application”.
I managed to hide the command prompt in by filling the entire row with spaces, works fine for me:
using System;
using System.IO;
static class Program
<
[DllImport(“kernel32.dll”)]
static extern bool AttachConsole(UInt32 dwProcessId = 0xffffffff);
[STAThread]
static void Main()
<
try
<
AttachConsole();
Console.Write(“r”); // go back to the first column of a console window
for (int i = 0; i Konsolenausgaben in einer WindowsForms Applikation « BigBasti’s Blog on January 17th, 2012 at 7:14 am
[…] Infos und auch eine kleine Diskussion gibts hier und hier. Share and […]
[…] answer points to an article about running a .Net WinForms application with a console. It uses the technique of calling AttachConsole after the program starts running. This has the […]
This is very helpful. I also want my WinFoms application to behave like Console application when I return a code(integer) from main method. Basically when I do that from Console application the %ERRORLEVEL% is set with return value and I want the same thing to happen when I run my WinForms type application from command prompt. How do I do that?
Any idea how to capture another process’ output? Say you’ve started a batch file from a cmd.exe process (pid 1234). Batch file creates output… Can we caputure this output from another process?
@Meraydin: Offhand, the easiest solution would be to redirect the batch file output to a text file, such as:
Then you can open and inspect the contents of the text file.
You made my day !
It’s the best solution I found to get exactly what I wanted.
Thank you !
very informative, Worked for me, as i want to print Exceptions on to the console rather than choosing MessageBox over form. Thank you
really simple ,windows form application so much fun 🙂
[…] Console Output from a WinForms Application : C# 411 – You may wish to enable your WinForms application to run from a console window or command line. And when it does, you probably want to send output messages to the …… […]
[…] answer points to an article about running a .Net WinForms application with a console. It uses the technique of calling AttachConsole after the program starts running. This has the […]