2010-08-25 140 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); 
     } 
    } 

这应该做你的要求。

相关问题