2010-08-25 280 views
17

問題:我有一個不應該被看到的控制檯程序。 現在(它重置IIS和刪除臨時文件。)如何隱藏控制檯窗口?

我能設法隱藏窗口後立即啓動這樣的:

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 
    } 

問題是這樣的顯示窗口一秒鐘,眨眼。 有沒有控制檯程序的任何構造函數,我可以在顯示之前隱藏窗口?

其次:

我用

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

,我不喜歡它的32。有沒有辦法做到這一點沒有DllImport?
.NET方式?

+0

爲什麼你不喜歡'user32.dll'的名字? – 2010-08-25 07:37:57

+2

'user32.dll'不是一個專門的32位DLL,並且可以在所有當前版本的Windows上使用,無論體系結構如何。這個名字是一個可以追溯到NT4的傳統。 – 2010-08-25 07:40:16

回答

33

如果您不需要控制檯(例如對於Console.WriteLine),則將應用程序構建選項更改爲Windows應用程序。

這會更改.exe標頭中的標誌,以便Windows在應用程序啓動時不分配控制檯會話。

+1

或使它成爲一個Windows服務,雖然它將有不同的生命週期 – 2010-08-25 07:55:25

+3

創建一個Windows應用程序並不創建Windows窗體 – abatishchev 2010-08-25 07:56:09

+0

@Grand Crofton:服務是爲長時間運行或重複的後臺任務,而不是用戶觸發像IIS重置一樣的操作。所以這裏的服務似乎不太合適。除非你想每隔5分鐘左右重置IIS,當然;-) – 2010-08-25 08:12:35

10

如果我明白你的問題,只是手動創建控制檯程序並隱藏控制檯窗口:

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

我做了一個WPF應用程序,其執行控制檯應用程序(在後臺工作)和重定向標準輸出,因此如果需要,您可以在窗口中顯示結果。作品一種享受,所以讓我知道如果你需要看更多的代碼(代碼工人,重定向,參數傳遞等)

+0

@Si:我認爲OP希望能夠通過雙擊它來啓動「無窗口控制檯程序」,例如,不一定以編程方式從其他程序中啓動。 – 2010-08-25 07:53:39

+0

的確,我不確定,以前有過同樣的需求。我無法捕獲的一件事是將着色的ANSI控制檯輸出到WPF中。請參閱http://stackoverflow.com/questions/1529254/capture-coloured-console-output-into-wpf-application – si618 2010-08-25 15:09:15

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(); 
} 

查看更多控制檯相關的API調用here

+2

請注意,不是拋出新的PInvokeExcpetion(),而是拋出新的Win32Exception()或拋出元帥.GetExceptionForHR(Marshal.GetHRForLastWin32Error());' 就足夠了。使用'Win32Exception()',您不必費心自己調用'GetLastError',然後將錯誤代碼映射爲有意義的消息。一切都已經爲你完成了。 – 2010-08-25 08:02:26

+0

@ 0xA3:感謝您的提示! – abatishchev 2010-08-25 08:10:25

+1

你真的應該在你的例子中包含GetStdHandle(我用enum來清楚int是什麼,而不是僅僅使用-11 ..) ** 私有枚舉StdHandle {Stdin = -10,Stdout = -11 ,Stderr = -12}; private static extern IntPtr GetStdHandle(StdHandle std); ** – Bostwick 2015-05-14 18:25:17

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); 
     } 
    } 

這應該做你的要求。