Why is the application output not displayed?

I have an application that has the following Main :

 static void Main(string[] args) { Console.WriteLine("started"); if (args.Length == 0) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } else { File.WriteAllText("./file.txt", "hello"); } } 

I want it to support command line launch, which should be used in some scenarios, and also works as a graphical application. However, if I run it from the command line and pass it a parameter, I see that the file is being created, but I do not see any output created by Console.WriteLine . Why is this?

+4
source share
6 answers

I think I found a problem, please forgive me if I am wrong.
When you create a GUI application and launch it from the console window, its standard output stream is not sent to the previously opened console window, therefore, it is not displayed.
But if you try to run yourexe.exe > test.txt , you can see everything you wrote with Console.WriteLine

+3
source

This will not work because

This is because the console window that launched your WinForms application belongs to the cmd.exe process, which is separate from your WinForms process.

I found this in this article , which also offers some workaround with AttachConsole Win32 Method

+2
source

It seems that you want to run the application in both console mode and GUI mode. This example does this. Basqually, you create a Form application and in the main conditional call of AllocConsole if you start it from Explorer. If you run from the command line that you will need to find by looking at the parent process, you can attach it to the console using AttachConsole . I hardcoded the values ​​here, but you can look at the arguments and decide to do something.

This app basically has three modes

  • bParentConsoleMode , which will use the parent console when launched from the command line
  • bUsingOwnConsole If you double-click in Explorer, you will need to create a new console.
  • Finally, when none of the above rules is true, it runs as a regular form application.

     static class Program { [DllImport("kernel32.dll")] static extern bool AttachConsole(int dwProcessId); private const int ATTACH_PARENT_PROCESS = -1; [DllImport("kernel32.dll")] private static extern bool AllocConsole(); [STAThread] static void Main() { bool bParentConsoleMode = true; bool bUsingOwnConsole = true; if (bParentConsoleMode) { AttachConsole(ATTACH_PARENT_PROCESS); Console.WriteLine("Using parent console"); Console.ReadLine(); } else if (bUsingOwnConsole) { AllocConsole(); Console.WriteLine("Using own console"); Console.ReadLine(); } else //gui mode { Console.WriteLine("This is cool"); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } } 
+2
source

See this post from Raymond Chen: How do I write a program that can be run as a console or GUI application?

Excerpts:

You cannot, but you can try to fake it.

[...]

There are some people who want to write what I call the “opportunistic” console program. These are programs that will use their parent's console if they are available, but do not want the console to be created for them if not. The kernel does not support this type of program, but this did not stop some people from using smart workarounds .

The problem is that the solution is "to connect to an existing console window for input and output or run as a console application with a graphical interface"? occurs before the start of the process. You cannot write code that makes this decision based on command line options.

Windows forces you to make a decision at compile time: this application will use the console (in this case it always has a console window and opens a new one if it was launched from the icon or the Start menu)), or it will not use the console (in in this case, he cannot direct input or output to the console window from which he was launched - he can, however, create a new console window ). If you want to always have a console, change the assembly type to "Console application"; if you do not want to have a console, leave it as a “Windows application”.

The smart workarounds cited in the Raymond post, in case of link decay, are devenv (Visual Studio) and ildasm:

In the case of VisualStudio, there are actually two binaries: devenv.com and devenv.exe. Devenv.com is a console application. Devenv.exe is a graphical application. When you enter devenv, due to the Win32 validation rule, devenv.com is executed. If there is no entry, devenv.com launches the devenv.exe file and exits it. If there are inputs, devenv.com treats them like a regular console application.

In the case of ildasm, there is only one binary file: ildasm.exe. It is first compiled as a GUI application. Later, editbin.exe is used to mark it as a console subsystem. In his main method, he determines whether to run it in console or graphical interface mode. If you need to run in GUI mode, it will resume working with the graphical interface.

+1
source

As Marko noted, did you try to set the output type of your application to the “Console Application”?

0
source

I used the following code to do something like this:

  Console.WriteLine("started"); if (args.Length == 0) { ProcessForConsole(argsParser); } else { NativeMethods.FreeConsole(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } 

. ,,.

  [DllImport("kernel32.dll", SetLastError = true)] public static extern int FreeConsole(); 

Install the main application in a console application and then FreeConsole to disconnect it.

A process can use the FreeConsole function to disconnect from the console. If other processes use the console, the console will not be destroyed, but a process called FreeConsole cannot refer to it. The console closes when the last process connected to it exits or calls FreeConsole.

From microsoft.

0
source

Source: https://habr.com/ru/post/1392052/


All Articles