C# - 启动不可见进程(CreateNoWindow 和 WindowStyle 不起作用?)

发布于 2024-09-04 15:18:41 字数 809 浏览 8 评论 0原文

我有 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运行但不显示?ㅤㅤㅤㅤㅤ

I have 2 programs (.exe) which I've created in .NET. We'll call them the Master and the Worker. The Master starts 1 or more Workers. The Worker will not be interacted with by the user, but it is a WinForms app that receives commands and runs WinForms components based on the commands it receives from the Master.

I want the Worker app to run completely hidden (except showing up in the Task Manager of course). I thought that I could accomplish this with the StartInfo.CreateNoWindow and StartInfo.WindowStyle properties, but I still see the Client.exe window and components in the form. However, it doesn't show up in the taskbar.

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

What do I need to do to let Client.exe run, but not show up?ㅤㅤㅤㅤㅤ

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

老子叫无熙 2024-09-11 15:18:41

您对 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。有关此的更多信息此处。这样做的缺点是,您有时会看到工作窗口在隐藏之前闪烁出现。例子:

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

Your usage of CreateNoWindow/WindowStyle works fine on my system with notepad.exe (e.g. it is hidden but running in the background), so it's probably something the WinForms app is doing. Some ideas:

Option 1: If you control the WinForms worker process, you can override Control.SetVisibleCore to always hide the form. If you don't want to always hide it, you can pass a command-line argument to it, e.g. /hide that will cause it to be hidden. Example (assuming there's already code-behind for the form):

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

With this, running MyForm.exe results in a process with a visible form. Running MyForm.exe /hide results in a process with a hidden form. You could pass the /hide argument from your master process, so then normal users running the application will still see it.

Option 2: You can hide the application after it starts by doing a P/Invoke to ShowWindow. More info on this here. This has the drawback that you can sometimes see the worker window flicker into existence before being hidden. Example:

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);
}
雾里花 2024-09-11 15:18:41

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

The problem is with UseShellExecute = false, set this to true and the process will be started as hidden. Using the shell to start the process understands how to make the application hidden, where as starting the process directly with UseShellExecute = false starts the process directly, and as Chris Schmich mentioned, you'd have to handle hiding the window from inside the client application. This might be more desirable if you want the option of running the application manually for debugging or testing purposes.

只是我以为 2024-09-11 15:18:41

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

You have to add base.Visibility = Visibility.Hidden; in Win Form application constructor.

盗心人 2024-09-11 15:18:41

由于我的声誉太低,我只能发布我的答案,可以评论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 有时不起作用。

Since my reputation is too low, i can only post my answer, ubable to comment Chris Schmich's answer.

Before start process, you can set WindowStyle = ProcessWindowStyle.Minimized to avoid window flicker.

Here is my code:

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

Finally thanks good answer provided by Chris Schmich, while ProcessWindowStyle.Hidden sometimes not work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文