C# - 制作Process.Start等到进程启动

时间:2011-06-17 18:18:55

标签: c# .net windows process

在继续使用方法之前,我需要确保进程正在运行。

陈述是:

Process.Start("popup.exe");

您可以执行WAIT命令或设置此值的延迟吗?

12 个答案:

答案 0 :(得分:118)

你的意思是等到它完成了吗?然后使用Process.WaitForExit

var process = new Process {
    StartInfo = new ProcessStartInfo {
        FileName = "popup.exe"
    }
};
process.Start();
process.WaitForExit();

或者,如果它是一个带有您正在等待进入消息循环的UI的应用程序,您可以说:

process.Start();
process.WaitForInputIdle();

最后,如果这些都不适用,只需Thread.Sleep一段合理的时间:

process.Start();
Thread.Sleep(1000); // sleep for one second

答案 1 :(得分:14)

我也需要这个,我检查过程的窗口标题。如果它是您期望的那个,您可以确定应用程序正在运行。我正在检查的应用程序需要一些时间来启动,这种方法对我来说很好。

var process = Process.Start("popup.exe");
while(process.MainWindowTitle != "Title")
{
    Thread.Sleep(10);
}

答案 2 :(得分:11)

ChrisG'的回答是正确的,但我们每次都需要刷新MainWindowTitle,最好检查一下空......就像这样:

import toastr from 'toastr';

答案 3 :(得分:7)

就像其他人已经说过的那样,你所要求的并不是很明显。我将假设你想要启动一个进程,然后在进程“准备就绪”时执行另一个操作。

当然,“准备就绪”是一个棘手的问题。根据您的需求,您可能会发现只需等待即可。但是,如果您需要更强大的解决方案,可以考虑使用命名Mutex来控制两个进程之间的控制流。

例如,在主进程中,您可以创建一个命名的互斥锁并启动一个等待的线程或任务。然后,您可以开始第二个过程。当该进程决定“它已准备就绪”时,它可以打开指定的互斥锁(当然,您必须使用相同的名称)并向第一个进程发出信号。

答案 4 :(得分:6)

首先:我知道这已经很老了,但仍然没有接受的答案,所以也许我的方法会帮助别人。 :)

我做的是解决这个问题:

process.Start();

while (true)
{
    try
    {
        var time = process.StartTime;
        break;
    }
    catch (Exception) {}
}

只要进程没有启动,关联var time = process.StartTime就会抛出异常。因此,一旦通过,就可以安全地假设流程正在运行并进一步使用它。我正在使用它来等待java进程启动,因为它需要一些时间。这样,它应该独立于运行应用程序的机器,而不是使用Thread.Sleep()

我知道这不是一个非常干净的解决方案,但是我能想到的唯一一个应该与性能无关的解决方案。

答案 5 :(得分:4)

我同意汤姆的观点。此外,要在执行Thread.Sleep时检查进程,请检查正在运行的进程。类似的东西:

bool found = 0;
while (!found)
{
    foreach (Process clsProcess in Process.GetProcesses())
        if (clsProcess.Name == Name)
            found = true;

    Thread.CurrentThread.Sleep(1000);
}

答案 6 :(得分:2)

在子进程启动之前,您确定Start方法是否返回?我始终认为Start同步启动子进程。

如果您想等到子进程完成某种初始化,那么您需要进程间通信 - 请参阅 Interprocess communication for Windows in C# (.NET 2.0)

答案 7 :(得分:1)

为了扩展@ChrisG的想法,请考虑使用process.MainWindowHandle并查看窗口消息循环是否响应。使用p /调用此Win32 api:SendMessageTimeout。 从那个链接:

  

如果功能成功,则返回   值非零。 SendMessageTimeout   不提供有关的信息   如果,个别窗户超时   使用HWND_BROADCAST。

     

如果函数失败或超时,则返回值为0.要获取   扩展错误信息,调用   GetLastError函数。如果GetLastError返回   ERROR_TIMEOUT,然后函数定时   进行。

答案 8 :(得分:0)

这是一个使用System.Threading.Timer的实现。为了它的目的可能有点多。

    private static bool StartProcess(string filePath, string processName)
    {
        if (!File.Exists(filePath))
            throw new InvalidOperationException($"Unknown filepath: {(string.IsNullOrEmpty(filePath) ? "EMPTY PATH" : filePath)}");

        var isRunning = false;

        using (var resetEvent = new ManualResetEvent(false))
        {

            void Callback(object state)
            {
                if (!IsProcessActive(processName)) return;
                isRunning = true;
                // ReSharper disable once AccessToDisposedClosure
                resetEvent.Set();
            }

            using (new Timer(Callback, null, 0, TimeSpan.FromSeconds(0.5).Milliseconds))
            {
                Process.Start(filePath);
                WaitHandle.WaitAny(new WaitHandle[] { resetEvent }, TimeSpan.FromSeconds(9));
            }
        }

        return isRunning;
    }

    private static bool StopProcess(string processName)
    {
        if (!IsProcessActive(processName)) return true;

        var isRunning = true;

        using (var resetEvent = new ManualResetEvent(false))
        {

            void Callback(object state)
            {
                if (IsProcessActive(processName)) return;
                isRunning = false;
                // ReSharper disable once AccessToDisposedClosure
                resetEvent.Set();
            }

            using (new Timer(Callback, null, 0, TimeSpan.FromSeconds(0.5).Milliseconds))
            {
                foreach (var process in Process.GetProcessesByName(processName))
                    process.Kill();
                WaitHandle.WaitAny(new WaitHandle[] { resetEvent }, TimeSpan.FromSeconds(9));
            }
        }

        return isRunning;
    }

    private static bool IsProcessActive(string processName)
    {
        return Process.GetProcessesByName(processName).Any();
    }

答案 9 :(得分:0)

public static class WinApi
{

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

    public static class Windows
    {
        public const int NORMAL = 1;
        public const int HIDE = 0;
        public const int RESTORE = 9;
        public const int SHOW = 5;
        public const int MAXIMIXED = 3;
    }

}

应用

String process_name = "notepad"
Process process;
process = Process.Start( process_name );

while (!WinApi.ShowWindow(process.MainWindowHandle, WinApi.Windows.NORMAL))
{
    Thread.Sleep(100);
    process.Refresh();
}

// Done!
// Continue your code here ...

答案 10 :(得分:0)

我使用了EventWaitHandle类。在父进程上,创建一个名为EventWaitHandle的事件的初始状态设置为非信号状态。父进程将阻塞,直到子进程调用Set方法,将事件的状态更改为已通知,如下所示。

家长程序:

'AND'

子进程:

using System;
using System.Threading;
using System.Diagnostics;

namespace MyParentProcess
{
    class Program
    {
        static void Main(string[] args)
        {
            EventWaitHandle ewh = null;
            try
            {
                ewh = new EventWaitHandle(false, EventResetMode.AutoReset, "CHILD_PROCESS_READY");

                Process process = Process.Start("MyChildProcess.exe", Process.GetCurrentProcess().Id.ToString());
                if (process != null)
                {
                    if (ewh.WaitOne(10000))
                    {
                        // Child process is ready.
                    }
                }
            }
            catch(Exception exception)
            { }
            finally
            {
                if (ewh != null)
                    ewh.Close();
            }
        }
    }
}

答案 11 :(得分:0)

您还可以通过尝试以下操作来检查启动的进程是否响应: while(process.responding)

相关问题