【问题标题】:How to run a C# console application with the console hidden如何在隐藏控制台的情况下运行 C# 控制台应用程序
【发布时间】:2010-10-24 14:23:06
【问题描述】:

有没有办法在执行控制台应用程序时隐藏控制台窗口?

我目前正在使用 Windows 窗体应用程序来启动控制台进程,但我不希望在任务运行时显示控制台窗口。

【问题讨论】:

  • 尝试从计划任务运行控制台应用程序。

标签: c# console-application


【解决方案1】:

如果您使用 ProcessStartInfo 类,您可以将窗口样式设置为隐藏 - 对于控制台(不是 GUI)应用程序,您必须将 CreateNoWindow 设置为 true

System.Diagnostics.ProcessStartInfo start =
      new System.Diagnostics.ProcessStartInfo();
start.FileName = dir + @"\Myprocesstostart.exe";
start.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; //Hides GUI
start.CreateNoWindow = true; //Hides console

【讨论】:

  • 正是我要发布的内容:)
  • 天哪——比乔恩还快的人! =)
  • 我不得不限制他的互联网连接才能打败他;)
  • 它不适用于调用命令行工具。使用 yourprocess.StartInfo.CreateNoWindow=true;相反,请参见下文。
  • 不隐藏控制台窗口,需要StartInfo.CreateNoWindow = true。
【解决方案2】:

我知道我没有准确回答你想要的,但我想知道你是否问对了问题。

你为什么不使用任何一个:

  1. Windows 服务
  2. 创建一个新线程并在其上运行您的进程

如果您只想运行一个进程,这些听起来像是更好的选择。

【讨论】:

  • 在很多情况下启动实用程序控制台应用程序是完全合法的。
  • 在我的情况下,由于我正在开发的软件使用客户端/服务器模型,因此需要一个单独的过程。
  • 创建新线程并不总能解决问题。有时您只是不想让烦人的窗口出现在后台。此外,如果你有一个 process.start 在循环中,那么你将无法完成任何工作,因为控制台窗口会弹出你的脸。
  • 我从任务计划程序启动无窗口实用程序控制台应用程序。不需要服务,也不需要派生线程的父进程。如果需要额外的输出,这些应用会写入 EventLog。
【解决方案3】:

您可以使用FreeConsole API 将控制台与进程分离:

[DllImport("kernel32.dll")]
static extern bool FreeConsole();

(当然这仅适用于您可以访问控制台应用程序的源代码)

【讨论】:

  • 我不想显示控制台。虽然FreeConsole 的功能与它的名字一样,但它不会阻止 Windows 在调用它之前显示控制台。
  • 然后将项目编译为 Windows 应用程序,而不是控制台应用程序
  • 郑重声明,这正是所需要的,谢谢。这也是正是标题所要求的:)所以为了其他谷歌航海者的利益,+1
  • 此外,[DllImport("kernel32.dll")] static extern bool AllocConsole(); 允许您从标准 Win32 应用程序使用控制台轻松运行
  • 适用于我的 .NET Core 2.2 应用程序 - 如果有人专门寻找这个。
【解决方案4】:

如果您正在创建一个不需要用户输入的程序,您始终可以将其创建为服务。服务不会显示任何类型的 UI。

【讨论】:

  • 但是如果您只想运行该进程直到它退出,例如通过从任务计划程序调用它,那么服务会因为它继续存在而带来不便。在某些情况下,将输出类型更改为 Windows 应用程序而不是将替代的 ProcessWindowStyle 更改为隐藏非常方便。
【解决方案5】:

如果您编写了控制台应用程序,则可以将其默认隐藏。

创建一个新的控制台应用程序,然后将“输出类型”类型更改为“Windows 应用程序”(在项目属性中完成)

【讨论】:

  • 我试图隐藏我自己的控制台,而不是调用其他东西然后隐藏它(就像公认的答案假设的那样) - 所以这对我来说是最好的。谢谢!
  • 谢谢哥们!这也是我一直在寻找的!
  • 接受的答案假设因为它在问题中说明。
  • 最简单的方式..真的很喜欢它..我们当然不想显示窗口,因为它会为我启动另一个进程..
  • 这个解决了 ProcessStartInfo 的问题,您可以在其中指定用户凭据并且该用户恰好已登录或当前用户。在这种情况下, CreateNoWindow 属性将被忽略,因此您始终会获得一个控制台窗口。通过将控制台应用程序设置为 Windows 应用程序但没有窗口,那么您将没有窗口。
【解决方案6】:

如果你使用的是进程类,那么你可以写

yourprocess.StartInfo.UseShellExecute = false;
yourprocess.StartInfo.CreateNoWindow = true;

yourprocess.start(); 之前,进程将被隐藏

【讨论】:

  • 如果您必须尽早停止该过程,祝您好运。 Process.Kill 突然终止。 Process.CloseMainWindow 失败。 GenerateConsoleCtrlEvent 无法向进程发送 ctrl+c 或 ctrl+break。进程中所有线程窗口的 WM_CLOSE 失败。似乎没有办法干净地结束以这两个参数值开始的进程。在这里查看我的问题:stackoverflow.com/questions/16139571/…
  • 谢谢,这是最简单的。此外,如果您拥有(或部门)控制台的代码,我发现这个互斥锁示例是最容易干净关闭的。 stackoverflow.com/a/31586184/1877412
  • @Triynko:你不能干净地终止任何进程,除非该进程积极合作。这不是标志或其他任何东西的问题。操作系统中没有任何东西可以触发干净关闭。这里的常见解决方案是使用一个可等待内核对象,它在控制进程中发出信号,当从属进程应该终止时。从属进程需要主动监控这个可等待对象的状态,并在收到信号后启动干净关闭。
【解决方案7】:

简单的答案是:转到控制台应用程序的属性(项目的属性)。在“应用程序”选项卡中,只需将“输出类型”更改为“Windows 应用程序”。就是这样。

【讨论】:

  • 靶心。这与创建不调用任何表单的 Windows 应用程序相同。
  • 这是正确答案。你的其他创可贴方法都没有。这是真正的正确答案。您希望您的应用程序从一开始就永远不会打开控制台。此外,您希望能够随时打开表单。因此,您只需在需要时调用表单。即当用户右键单击系统托盘图标并选择首选项时,将调用我们的表单。这是正确的答案!!!
【解决方案8】:

虽然这里的其他答案说您可以将“输出类型”更改为“Windows 应用程序”,但请注意,这意味着您不能使用 Console.In,因为它将成为 NullStreamReader。

Console.OutConsole.Error 似乎仍然可以正常工作。

【讨论】:

  • 你是认真的吗?当没有控制台输入内容时,为什么有人会使用Console.In?可以通过Console.In 访问的东西应该来自哪里?这根本没有任何意义。换句话说:在这种情况下,Console.InNullStreamReader 是完全明显和合乎逻辑的。
  • @RobertS。也许是一根管子。 IE。另一个程序的输出。当我发现这一点时,这就是我的用例。
【解决方案9】:

如果你对输出感兴趣,可以使用这个函数:

private static string ExecCommand(string filename, string arguments)
{
    Process process = new Process();
    ProcessStartInfo psi = new ProcessStartInfo(filename);
    psi.Arguments = arguments;
    psi.CreateNoWindow = true;
    psi.RedirectStandardOutput = true;
    psi.RedirectStandardError = true;
    psi.UseShellExecute = false;
    process.StartInfo = psi;

    StringBuilder output = new StringBuilder();
    process.OutputDataReceived += (sender, e) => { output.AppendLine(e.Data); };
    process.ErrorDataReceived += (sender, e) => { output.AppendLine(e.Data); };

    // run the process
    process.Start();

    // start reading output to events
    process.BeginOutputReadLine();
    process.BeginErrorReadLine();

    // wait for process to exit
    process.WaitForExit();

    if (process.ExitCode != 0)
        throw new Exception("Command " + psi.FileName + " returned exit code " + process.ExitCode);

    return output.ToString();
}

它运行给定的命令行程序,等待它完成并将输出作为字符串返回。

【讨论】:

    【解决方案10】:

    将此添加到您的类以导入 DLL 文件:

    [DllImport("user32.dll")] 
    static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 
    
    [DllImport("kernel32.dll")] 
    static extern IntPtr GetConsoleWindow();
    
    const int SW_HIDE = 0;
    const int SW_SHOW = 5;
    

    然后如果你想隐藏它使用这个命令:

     var handle = GetConsoleWindow();
     ShowWindow(handle, SW_HIDE);
    

    如果你想显示控制台:

    var handle = GetConsoleWindow();
    ShowWindow(handle, SW_SHOW);
    

    【讨论】:

    • [DllImport("user32.dll")] static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("kernel32.dll")] 静态外部 IntPtr GetConsoleWindow();常量 int SW_HIDE = 0;常量 int SW_SHOW = 5;
    【解决方案11】:

    随便写

    ProcessStartInfo psi= new ProcessStartInfo("cmd.exe");
    ......
    
    psi.CreateNoWindow = true;
    

    【讨论】:

      【解决方案12】:

      根据上面 Adam Markowitz 的回答,以下对我有用:

      process = new Process();
      process.StartInfo = new ProcessStartInfo("cmd.exe", "/k \"" + CmdFilePath + "\"");
      process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
      //process.StartInfo.UseShellExecute = false;
      //process.StartInfo.CreateNoWindow = true;
      process.Start();
      

      【讨论】:

        【解决方案13】:

        我有一个通用的解决方案要分享:

        using System;
        using System.Runtime.InteropServices;
        
        namespace WhateverNamepaceYouAreUsing
        {
            class Magician
            {
                [DllImport("kernel32.dll")]
                static extern IntPtr GetConsoleWindow();
        
                [DllImport("user32.dll")]
                static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
        
                const int HIDE = 0;
                const int SHOW = 5;
        
                public static void DisappearConsole()
                {
                    ShowWindow(GetConsoleWindow(), HIDE);
                }
            }
        }
        

        只需将此类包含在您的项目中,然后调用Magician.DisappearConsole();

        当您通过单击启动程序时,控制台将闪烁。从命令提示符执行时,命令提示符在执行后很快消失。

        我这样做是为了一个 Discord Bot,它作为一个不可见的进程在我的计算机后台永远运行。这比让 TopShelf 为我工作更容易。在我在其他地方找到的代码的帮助下写这篇文章之前,一些 TopShelf 教程让我失望了。 ;P

        我还尝试简单地更改 Visual Studio > 项目 > 属性 > 应用程序中的设置以作为 Windows 应用程序而不是控制台应用程序启动,并且我的项目的某些内容阻止了它隐藏我的控制台 - 可能是因为 DSharpPlus 要求启动一个启动时控制台。我不知道。不管是什么原因,这个类让我可以在控制台弹出后轻松杀死它。

        希望这位魔术师能帮助别人。 ;)

        【讨论】:

          猜你喜欢
          • 2015-08-17
          • 1970-01-01
          • 1970-01-01
          • 2011-04-20
          • 1970-01-01
          • 2023-03-24
          • 1970-01-01
          • 2011-04-04
          • 1970-01-01
          相关资源
          最近更新 更多