【问题标题】:C# - Launch Invisible Process (CreateNoWindow & WindowStyle not working?)C# - 启动不可见进程(CreateNoWindow 和 WindowStyle 不起作用?)
【发布时间】:2011-03-01 23:19:34
【问题描述】:

我有 2 个在 .NET 中创建的程序 (.exe)。我们称他们为 Master 和 Worker。 Master 启动 1 个或多个 Worker。 Worker 不会与用户交互,但它是一个 WinForms 应用程序,它接收命令并根据从 Master 接收到的命令运行 WinForms 组件。

我希望 Worker 应用程序完全隐藏运行(当然,除了显示在任务管理器中)。我认为我可以使用 StartInfo.CreateNoWindowStartInfo.WindowStyle 属性来完成此操作,但我仍然在表单中看到 Client.exe 窗口和组件。但是,它不会显示在任务栏中。

   Process process = new Process
      {
          EnableRaisingEvents = true,
          StartInfo =
              {
                  CreateNoWindow = true,
                  WindowStyle = ProcessWindowStyle.Hidden,
                  FileName = "Client.exe",
                  UseShellExecute = false,
                  ErrorDialog = false,
              }
      };

我需要怎么做才能让 Client.exe 运行,但不显示?ㅤㅤㅤㅤㅤ

【问题讨论】:

    标签: c# .net winforms process processstartinfo


    【解决方案1】:

    由于我的声誉太低,我只能发布我的答案,可以评论 Chris Schmich 的答案。

    在启动进程之前,可以设置WindowStyle = ProcessWindowStyle.Minimized以避免窗口闪烁。

    这是我的代码:

    private const int SW_HIDE = 0;
    
    [DllImport("user32.dll")]
    private static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);
    
    public int RunWithoutWindow(string exePath)
    {
        var startInfo = new ProcessStartInfo(exePath)
        {
            WindowStyle = ProcessWindowStyle.Minimized
        };
    
        var process = Process.Start(startInfo);
    
        while (process.MainWindowHandle == IntPtr.Zero)
        {
            process.Refresh();
        }
    
        ShowWindow(process.MainWindowHandle, SW_HIDE);
    
        return process.Id;
    }
    

    最后感谢 Chris Schmich 提供的好答案,而 ProcessWindowStyle.Hidden 有时不起作用。

    【讨论】:

      【解决方案2】:

      您必须在 Win Form 应用程序构造函数中添加base.Visibility = Visibility.Hidden;

      【讨论】:

        【解决方案3】:

        问题在于UseShellExecute = false,将其设置为true,该进程将以隐藏状态启动。使用 shell 启动进程了解如何隐藏应用程序,因为直接使用 UseShellExecute = false 启动进程直接启动进程,正如 Chris Schmich 所提到的,您必须处理从客户端应用程序内部隐藏窗口.如果您希望选择手动运行应用程序以进行调试或测试,这可能更理想。

        【讨论】:

        • 杰夫,感谢您的 cmets。不幸的是,这对我也不起作用。我认为它一定与我表单上的组件有关,但我不知道为什么会出现问题。您能否详细解释一下“使用 shell 启动进程了解如何隐藏应用程序,而使用 UseShellExecute = false 直接启动进程则直接启动进程”?谢谢。
        • 这对我有用。真的要这么难吗?
        【解决方案4】:

        您对 CreateNoWindow/WindowStyle 的使用在我的带有 notepad.exe 的系统上运行良好(例如,它被隐藏但在后台运行),所以这可能是 WinForms 应用程序正在做的事情。一些想法:

        选项 1: 如果您控制 WinForms 工作进程,则可以覆盖 Control.SetVisibleCore 以始终隐藏表单。如果您不想总是隐藏它,可以将命令行参数传递给它,例如/hide 这将导致它被隐藏。示例(假设表单已经有代码隐藏):

        public partial class MyForm : Form
        {
            public MyForm()
            {
                InitializeComponent();
            }
        
            protected override void SetVisibleCore(bool value)
            {
                // You'd probably want to parse the command line.
                if (Environment.CommandLine.Contains("/hide"))
                    base.SetVisibleCore(false);
                else
                    base.SetVisibleCore(value);
            }
        }
        

        这样,运行MyForm.exe 会产生一个具有可见表单的进程。运行MyForm.exe /hide 会导致一个带有隐藏表单的进程。您可以从您的主进程传递/hide 参数,这样运行该应用程序的普通用户仍然可以看到它。

        选项 2: 您可以在应用程序启动后隐藏应用程序,方法是向 ShowWindow 发送 P/Invoke。有关此here 的更多信息。这样做的缺点是您有时会看到工作窗口在隐藏之前闪烁。示例:

        class Program
        {
            public static void Main(string[] args)
            {
                ProcessStartInfo psi = new ProcessStartInfo()
                {
                    FileName = @"C:\windows\system32\notepad.exe",
                };
        
                Process process = Process.Start(psi);
        
                // Wait until the process has a main window handle.
                while (process.MainWindowHandle == IntPtr.Zero)
                {
                    process.Refresh();
                }
        
                ShowWindow(process.MainWindowHandle, SW_HIDE);
            }
        
            const int SW_HIDE = 0;
        
            [DllImport("user32.dll")]
            static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
        }
        

        【讨论】:

        • 克里斯,非常感谢您的建议。我会试一试并报告。我也认为这是我在 WinForms 中的一些问题,但 MSDN 文档并不暗示任何东西都可以覆盖或禁用这些选项。
        • 更新。所以,我尝试了 ShowWindow 和 SetVisibleCore 方法,但都没有工作。我什至尝试在 Worker 进程中设置主窗体不可见(form.Visible = false)。他们都没有工作。这可能与时间有关 - 我是否需要等到我的 WebBrowser 控件加载浏览器或类似的奇怪东西?谢谢。
        • @Chad:你在主进程中执行ShowWindow,在工作进程中执行SetVisibleCore,对吗?您是否尝试在SetVisibleCore 中设置断点?它会被击中吗?您还可以尝试处理一些表单事件(请参阅msdn.microsoft.com/en-us/library/…),例如LoadGotFocusVisibleChangedActivated,然后尝试更改那里的可见性。你在用System.Windows.Forms.WebBrowser吗?通过使用SetVisibleCore 方法,我能够隐藏承载该控件的表单。
        • 是的,ShowWindow 在 Master 中,SetVisibleCore 在 Worker 中。我在 Worker 中打印出 Form.Visible,它在表单的构造函数中为“假”。现在,我将查看这些事件,看看其他地方的可见性是否正在发生变化。我的组件:内部类 FlashWebBrowser:WebBrowser { protected override void WndProc(ref Message m) { switch (m.Msg) { case 0x021: case 0x201: case 0x204: case 0x207: base.DefWndProc(ref m);返回; } base.WndProc(ref m); } } 通过:tiredblogger.wordpress.com/2008/01/03/…
        • 所以,我尝试拦截 VisibleChanged 并在触发时设置 Visible = false。这几乎 100% 有效。当 Worker 加载时,我仍然看到一点点闪烁。现在,我可以忍受它并回到更重要的功能上。感谢您的所有帮助 - 您得到了答案。
        猜你喜欢
        • 2011-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-14
        • 2011-12-13
        相关资源
        最近更新 更多