2012-03-28 10 views
8

Ich möchte in der Lage sein, mein Programm von der Konsole ähnlich wie wget -b zu lösen. Ein Codefragment könnte so aussehenC# schließen Standard aus

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.*/ 
} 

Aber System.Console.Out.Close(); nicht das Richtige tun.

Um zu verdeutlichen, die "richtige Sache" ist, wenn dieses Programm von der Konsole ausgeführt wird, sollte die Eingabeaufforderung wieder erscheinen. Oder, wenn dieses Programm von explorer.exe ausgeführt wird, sollte das Konsolenfenster geschlossen werden.

Bitte lassen Sie mich wissen, wenn ich nicht klar bin.

+0

nur um sicher zu sein, dass ich Ihre Frage verstanden: Wenn Sie yourprogram.exe im Cmd-Fenster eingeben, sollte ein neues erscheinen. Wenn du die Anwendung im Explorer doppelt klickst, willst du die Konsole geschlossen haben? Was willst du mit deiner Bewerbung machen? –

+0

Eine Konsolenanwendung ohne die Konsole? Ich kann es kaum erwarten, die Antwort darauf zu sehen ... –

+1

Wenn Sie eine lang laufende Anwendung möchten, die im Hintergrund bleibt, benötigen Sie einen Windows-Dienst. Wenn Sie Ihre Anwendung nur regelmäßig starten möchten, sollten Sie sie mit dem Taskplaner starten. – jlafay

Antwort

1

Die Quelle für wget, auf die Sie verweisen, ist verfügbar here. Sie werden feststellen, dass in den Zeilen mswindows.c 193 - 314 eine Fork-Prozedur implementiert ist. Sie erzeugen eine neue Instanz von wget und übergeben sie die gleichen Parameter.

Die Kommentare sind informativ, auch:

Windows-unterstützt nicht die fork() nennen; Wir fälschen es also, indem wir eine andere Kopie von Wget mit denselben Argumenten aufrufen, mit denen wir aufgerufen wurden.

Und auf der Linie 102:

Unter Windows 9x, wenn wir von einem 16-Bit-Prozess ins Leben gerufen wurden ... soll der übergeordnete Prozess sofort wieder aufnehmen. Unter NT ... ist dies eine vergebliche Geste, da die Eltern darauf warten, dass wir aufhören, bevor wir fortfahren.

Die kurze Antwort scheint zu sein: "Tu das nicht."

+0

Ja - Sie könnten es vortäuschen oder sehr nahe kommen, aber es ist sehr streng 'nicht ermutigt' –

+0

Können Sie an eine andere Implementierung denken? –

+0

Wenn es Ihnen nichts ausmacht, mich zu fragen - was ist der Zweck, etwas zu drucken/etwas an die Konsole zu senden, bevor Sie tun ... was auch immer der Rest der Konsole tut? Würde die Trennung der beiden Hälften sinnvoll sein? Wäre ein laufender Dienst, an den eine Befehlszeilenkomponente einen Befehl senden kann und dann beendet, sinnvoll? –

1

Es sind 3 Kanäle für jede laufende Konsole verfügbar: STDIN, STDOUT, STDERR. Traditionell müssen alle 3 geschlossen werden, damit eine App die Konsole freigibt. In Windows scheint es jedoch eine API-Methode dafür zu geben: FreeConsole ... und pinvoke.net.

Edit: Ein weiterer SO-Post sagt, es ist nicht möglich, ohne einen Hintergrundprozess zu starten: How to make a windowless/command-line application return but continue executing in background? ... In Unix würde es mit einem fork(); reichen.

+0

Das funktioniert nicht. 'static void Haupt (string [] args) {System.Console.Out.Close(); System.Console.In.Close(); System.Console.Error.Close(); System.Console.WriteLine ("detatched.");} 'Zeigt an, dass die Konsole nicht getrennt ist. –

+0

Ich habe 'FreeConsole' versucht. Es scheint * fast * zu funktionieren. Ich kann die Konsole nicht mehr verwenden, um nach dem Freigeben in Standardausgabe zu schreiben, aber der Befehlsinterpreter erhält die Konsole immer noch nicht zurück. –

+0

@LimitedAtonement hast du deine Anwendung gestartet, indem du cmd.exe ausgeführt hast und dann die Anwendung ausgeführt hast? Um zu der Shell zurückzukehren, benötigen Sie eine Kopie von cmd.exe, die mit derselben Konsole verbunden ist. –

0

Um zu verdeutlichen, die "richtige Sache" ist, wenn dieses Programm von der Konsole ausgeführt wird, sollte die Eingabeaufforderung wieder erscheinen. Oder, wenn Sie dieses Programm von explorer.exe ausführen, sollte das Konsolenfenster geschlossen werden.

Es ist nicht so, dass Sie das "Konsolenfenster [zu] schließen möchten", Sie möchten, dass es nicht existiert. Es gibt einen sehr einfachen Weg, um zu bekommen, was Sie wollen: Erstellen Sie keine Konsolen-App. :-)

Wenn Sie über die Befehlszeile erstellen, verwenden Sie CSC /target:winexe .... Dadurch wird ein Windows-Programm erstellt, das keiner Befehlszeile zugeordnet wird.

+0

Das ist nicht genau meine Absicht. Ich möchte eine Konsole für eine Weile haben, dann möchte ich mich von ihr lösen. Ich habe die Frage vor einiger Zeit bearbeitet, um diese Anforderung zu klären. Das Codebeispiel könnte jetzt klarer sein. –

1

Statt eine Konsolenanwendung zu erstellen und dann Probleme mit dem Aufruf von FreeConsole hat, könnten Sie in der Lage zu bekommen, was Sie wollen, indem eine normale Windows-Anwendung erstellen, ohne GUI, die AllocConsole/AttachConsole/FreeConsole nach Bedarf verwendet.

Auf diese Weise haben Sie eine App, die im Hintergrund ausgeführt werden kann, aber ein Konsolenfenster nach Bedarf anzeigen und ausblenden kann. Obwohl, soweit ich mich erinnere, gibt es einige Unterschiede zwischen diesen Konsolenfenstern und normalen Windows-Eingabeaufforderungen, so dass es für das, was Sie wollen, nicht funktioniert.

+0

Danke für die Antwort. Es ist sicherlich eine Idee, ein neues Konsolenfenster zu öffnen, aber ich wollte nur mit dem vorhandenen Konsolenfenster interagieren. Ich glaube nicht, dass ich Probleme mit FreeConsole habe. es handelt so, wie es "sollte". Ich kenne "AllocConsole" usw. Das Problem ist, dass der Befehlsinterpreter (cmd oder powershell) darauf wartet, dass der * Prozess * beendet wird, bevor er zum Befehlsinterpreter zurückkehrt. Danke noch einmal. –