C# close standard out
Asked Answered
M

4

8

I would like to be able to detach my program from the console much like wget -b. A code fragment might look like

static void Main(string[] args)
{
    var settings = new Settings(args);
    if (settings.Background)
    {
        /*Tell the user what's going on.*/
        System.Console.WriteLine("Detatching from console. The program will still be running.");
        System.Console.Out.Close();
    }
    /*do work then exit.*/
}

But System.Console.Out.Close(); doesn't do the right thing.

To clarify, the "right thing" is, when running this program from the console, the prompt should re-appear. Or, when running this program from explorer.exe, the console window should close.

Please let me know if I am not being clear.

Morion answered 28/3, 2012 at 17:57 Comment(12)
just to be sure, that i understood your question: if you type yourprogram.exe in the cmd-window a new should appear. if you double click the application in explorer then you wanna have the console closed? what do you wanna do with your application?Careful
A console application without the console? Can't wait to see the answer to this...Matthieu
If you're wanting a long running application that stays in the background, you're wanting a windows service. If you just want to periodically launch your application you might consider launching it with task scheduler.Shanon
I don't think that's the right thing. Closing stdout would not mean that execution would return to the command prompt. The program terminating would cause that. If you want to start the program and return the command propmpt, you could spawn it with start on the command line.Turtledove
AFAIK there is a windows API function to detach from the consoleRadbun
@MarioFraiß No, I don't want a new window to appear. The normal behaviour is fine: the invoked process (this program we're talking about) takes over console in/out operations. Then, when the program ends, the console goes back to the command interpreter. I'm wanting my program to NOT end, and the console goes back to command interpreter.Morion
@CodeInChaos Thanks for suggesting that. It reminds me of FreeConsole. I tried it, but my program just hangs :( .Morion
@JamesMichaelHare "The program terminating would cause that." No doubt, but you can run wget -b and get the behaviour I'm wanting. I'm not wanting the program to be headless from the start. I would like, for instance, for the program to print a line to console, then detach, giving the user the command interpreter again.Morion
@LimitedAtonement do you mean wget -b on Linux? Or in Cygwin? You do realize that linux shells (including bash on cygwin) and windows shell are completely different animals, right?Accommodative
@ChrisShain Thanks for asking. GNU has put out a lot of windows stuff such as gnuwin32.sourceforge.net/packages/wget.htm . Be sure to check out gnuwin32.sourceforge.net/packages/coreutils.htm , too.Morion
I wonder if, albeit dangerous, spawning a new thread to do your after-console stuff might be what you want, and letting the initial thread terminate.Earthen
@CrisCarew I'm almost positive that won't work. The parent process waits for the child process to terminate. Spawning a new non-background thread will keep the process from terminating.Morion
M
1

The source for wget to which you refer is available here. You'll notice that in mswindows.c lines 193 - 314, a fork procedure is implemented. They spawn a new instance of wget and pass it the same parameters.

The comments are informative, too:

Windows doesn't support the fork() call; so we fake it by invoking another copy of Wget with the same arguments with which we were invoked.

And on line 102:

Under Windows 9x, if we were launched from a 16-bit process ... the parent process should resume right away. Under NT ... this is a futile gesture as the parent will wait for us to terminate before resuming.

The short answer seems to be "Don't do that."

Morion answered 28/3, 2012 at 19:9 Comment(4)
Yes - you could fake it or come very close, but it is very strictly 'not encouraged'Earthen
Can you think of another implementation?Morion
If you don't mind me asking - what is the purpose of printing something/returning something to the console before doing...whatever it is the rest of the console does? Would separating the two halves make sense? Would a running service, which a command line component can send a command to and then terminate make sense?Earthen
@CrisCarew Well, for my particular program, no it wouldn't make sense. Imade a console program to watch the file system and run a command when files change. This shouldn't be a service. The question turned general quickly after the specific instance (in fact, I don't think that forking to the background would be a good idea for this particular project, I was just thinking about it), and I started wondering, "How would I do that?". Your suggestion would probably make sense in some situations.Morion
A
1

There are 3 channels open for any console app running: STDIN, STDOUT, STDERR. Traditionally all 3 needs to be closed for an app to release the console.

In Windows there does however seem to be an API method for doing so: FreeConsole ... and pinvoke.net.

Edit: Another SO post says it isn't possible without starting a background process: How to make a windowless / command-line application return but continue executing in background? ... In Unix it would be enough with a fork();.

Absent answered 28/3, 2012 at 18:43 Comment(4)
That doesn't work. static void Main(string[] args){System.Console.Out.Close(); System.Console.In.Close(); System.Console.Error.Close(); System.Console.WriteLine("detatched.");} shows that the console isn't detached.Morion
I tried FreeConsole. It seems to almost work. I can no longer use the console to write to standard out after freeing it, but the command interpreter still doesn't get the console back.Morion
@LimitedAtonement did you start your application by running cmd.exe, then running the application? In order to get back to the shell, you'd need a copy of cmd.exe connected to the same console.Accommodative
I run powershell, then my application. What do you mean "a copy of cmd.exe connected to the same console"? There seems to be one connected to the console (currently on hold while my process runs), why would I need another?Morion
M
1

The source for wget to which you refer is available here. You'll notice that in mswindows.c lines 193 - 314, a fork procedure is implemented. They spawn a new instance of wget and pass it the same parameters.

The comments are informative, too:

Windows doesn't support the fork() call; so we fake it by invoking another copy of Wget with the same arguments with which we were invoked.

And on line 102:

Under Windows 9x, if we were launched from a 16-bit process ... the parent process should resume right away. Under NT ... this is a futile gesture as the parent will wait for us to terminate before resuming.

The short answer seems to be "Don't do that."

Morion answered 28/3, 2012 at 19:9 Comment(4)
Yes - you could fake it or come very close, but it is very strictly 'not encouraged'Earthen
Can you think of another implementation?Morion
If you don't mind me asking - what is the purpose of printing something/returning something to the console before doing...whatever it is the rest of the console does? Would separating the two halves make sense? Would a running service, which a command line component can send a command to and then terminate make sense?Earthen
@CrisCarew Well, for my particular program, no it wouldn't make sense. Imade a console program to watch the file system and run a command when files change. This shouldn't be a service. The question turned general quickly after the specific instance (in fact, I don't think that forking to the background would be a good idea for this particular project, I was just thinking about it), and I started wondering, "How would I do that?". Your suggestion would probably make sense in some situations.Morion
T
1

Instead of creating a console app and then having problems with the call to FreeConsole, you might be able to get what you want by creating a normal Windows app, without a GUI, that uses AllocConsole/AttachConsole/FreeConsole as needed.

That way you've got an app that can run in the background but that can show and hide a console window as needed. Though as far as I remember, there are some differences between these console windows and normal Windows command prompts, so it might not work for what you want.

Templeton answered 29/3, 2012 at 17:2 Comment(1)
Thanks for the answer. It's certainly an idea to open a new console window, but I was hoping to only interact with the existing console window. I don't think I'm having problems with FreeConsole; it's acting as it "should". I'm aware of AllocConsole, etc. The problem really is that the command interpreter (cmd or powershell) waits for the process to end before returning to the command interpreter. Thanks again.Morion
C
0

To clarify, the "right thing" is, when running this program from the console, the prompt should re-appear. Or, when running this program from explorer.exe, the console window should close.

It's not that you want the "console window [to] close", you want it to not exist. There's a very easy way to get what you want: don't build a console app. :-)

If building from the command line, use CSC /target:winexe .... This will create a Windows program that will never be associated with any command line.

Cecillececily answered 28/3, 2012 at 18:44 Comment(1)
That's not exactly my intent. I want a console for a little while, then I want to detach from it. I edited the question a little while ago to clarify this requirement. The code example might be more clear now.Morion

© 2022 - 2024 — McMap. All rights reserved.