2010-08-25 15 views
17

Frage: Ich habe ein Konsolenprogramm, das nicht gesehen werden sollte. (Es setzt IIS und löscht temporäre Dateien.)Wie kann ich ein Konsolenfenster ausblenden?

Im Moment kann ich das Fenster direkt nach dem Start wie folgt verstecken verwalten zu:

für ein Blinzeln eines zweiten
static void Main(string[] args) 
{ 
    var currentProcess = System.Diagnostics.Process.GetCurrentProcess(); 
    Console.WriteLine(currentProcess.MainWindowTitle); 

    IntPtr hWnd = currentProcess.MainWindowHandle;//FindWindow(null, "Your console windows caption"); //put your console window caption here 
    if (hWnd != IntPtr.Zero) 
    { 
     //Hide the window 
     ShowWindow(hWnd, 0); // 0 = SW_HIDE 
    } 

Das Problem ist, das zeigt das Fenster . Gibt es einen Konstruktor für ein Konsolenprogramm, wo ich das Fenster verstecken kann, bevor es angezeigt wird?

Und zweitens:

Ich benutze

[System.Runtime.InteropServices.DllImport("user32.dll")] 
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 

und ich weiß nicht wie die 32 darin. Gibt es eine Möglichkeit, dies ohne DllImport zu tun?
Ein .NET Weg?

+0

Warum magst du den Namen von 'user32.dll' nicht? –

+2

'user32.dll' ist nicht speziell eine 32-Bit-DLL und ist in allen aktuellen Versionen von Windows verfügbar, unabhängig von der Architektur. Der Name ist ein Vermächtnis, das auf NT4 zurückgeht. –

Antwort

33

Wenn Sie die Konsole nicht benötigen (z. B. für), ändern Sie die Build-Optionen für Anwendungen zu einer Windows-Anwendung.

Dadurch wird ein Flag im Header .exe geändert, sodass Windows beim Start der Anwendung keine Konsolensitzung zuweist.

+1

Oder machen Sie es zu einem Windows-Dienst, obwohl das einen anderen Lebenszyklus haben wird –

+3

Erstellen Sie eine Windows-Anwendung und erstellen Sie kein Windows-Formular – abatishchev

+0

@Grand Crofton: Dienste sind für eine lange oder wiederholte Hintergrundaufgaben, nicht für Benutzer ausgelöst Aktionen wie ein IIS-Reset. Also ein Service scheint hier nicht angebracht. Es sei denn, Sie möchten IIS alle 5 Minuten oder so zurücksetzen, natürlich ;-) –

10

Wenn ich verstehe Ihre Frage, erstellen Sie einfach die Konsole Prozess manuell und verstecken das Konsolenfenster:

Process process = new Process(); 
process.StartInfo.FileName = "Bogus.exe"; 
process.StartInfo.UseShellExecute = false; 
process.StartInfo.RedirectStandardOutput = true; 
process.StartInfo.CreateNoWindow = true; 

Ich tue dies für eine WPF-Anwendung, die eine Konsolenanwendung (in einem Hintergrundarbeiter) führt und leitet Standard Ausgabe, damit Sie das Ergebnis bei Bedarf in einem Fenster anzeigen können. Funktioniert ein Genuss lassen Sie mich so, wenn Sie mehr Code (Arbeiter-Code, Umleitung, Argumentübergabe, etc.) müssen sehen

+0

@Si: Ich denke, dass das OP in der Lage sein soll, das "no-window console program" durch Doppelklicken zu starten, zum Beispiel nicht unbedingt programmatisch aus einem anderen Programm. –

+0

Stimmt, ich war mir nicht sicher und hatte vorher das gleiche Bedürfnis. Eine Sache, die ich nicht erfassen kann, ist farbige ANSI-Konsolenausgabe in WPF. Siehe http://StackOverflow.com/Questions/1529254/capture-coloured-console-output-into-wpf-application – si618

3
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
private static extern bool CloseHandle(IntPtr handle); 

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
private static extern bool FreeConsole(); 

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall, SetLastError = true)] 
private static extern IntPtr GetStdHandle([MarshalAs(UnmanagedType.I4)]int nStdHandle); 

// see the comment below 
private enum StdHandle 
{ 
    StdIn = -10, 
    StdOut = -11, 
    StdErr = -12 
}; 

void HideConsole() 
{ 
    var ptr = GetStdHandle((int)StdHandle.StdOut); 
    if (!CloseHandle(ptr)) 
     throw new Win32Exception(); 

    ptr = IntPtr.Zero; 

    if (!FreeConsole()) 
     throw new Win32Exception(); 
} 

Weitere Konsole bezogene API-Aufrufe here

+2

Beachten Sie, dass statt "neue PInvokeExcpetion() werfen" normalerweise "neue Win32Exception() werfen" oder "Marshal werfen" .GetExceptionForHR (Marshal.GetHRForLastWin32Error()); ' ist ausreichend. Mit 'Win32Exception()' müssen Sie nicht selbst "GetLastError" aufrufen und dann den Fehlercode einer aussagekräftigen Nachricht zuordnen. Alles ist bereits für dich erledigt. –

+0

@ 0xA3: Danke für den Tipp! – abatishchev

+1

Sie sollten wirklich GetStdHandle in Ihrem Beispiel enthalten haben (ich habe eine enum verwendet, um klar zu machen, was die int sind, anstatt nur -11 zu verwenden) ** private enum StdHandle {Stdin = -10, Stdout = -11 , Stderr = -12}; private statisch extern IntPtr GetStdHandle (StdHandle Std); ** – Bostwick

2
[DllImport("user32.dll")] 
    public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 
    [DllImport("kernel32")] 
    public static extern IntPtr GetConsoleWindow(); 
    [DllImport("Kernel32")] 
    private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add); 

    static void Main(string[] args) 
    { 
     IntPtr hConsole = GetConsoleWindow(); 
     if (IntPtr.Zero != hConsole) 
     { 
      ShowWindow(hConsole, 0); 
     } 
    } 

Dies sollte Mach was du fragst.

Verwandte Themen