C#-创建流程。启动—等待流程启动

C#-创建流程。启动—等待流程启动,c#,.net,windows,process,C#,.net,Windows,Process,在继续使用方法之前,我需要确保流程正在运行 声明如下: Process.Start("popup.exe"); 您可以执行等待命令或设置此值的延迟吗?您的意思是等待,直到完成为止?然后使用Process.WaitForExit: var process = new Process { StartInfo = new ProcessStartInfo { FileName = "popup.exe" } }; process.Start(); process.Wa

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

声明如下:

Process.Start("popup.exe");

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

您的意思是等待,直到完成为止?然后使用
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

您确定
Start
方法在子进程启动之前返回吗?我总是觉得
Start
同步启动子进程


如果要等到子进程完成某种初始化,则需要进程间通信-请参阅。

我同意Tom的观点。此外,要在执行Thread.Sleep时检查进程,请检查正在运行的进程。比如:

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

    Thread.CurrentThread.Sleep(1000);
}

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

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

正如其他人已经说过的那样,你的问题并不明显。我假设您希望启动一个流程,然后在流程“准备就绪”时执行另一个操作

当然,“准备好了”是个棘手的问题。根据你的需要,你可能会发现仅仅等待就足够了。但是,如果需要更健壮的解决方案,可以考虑使用命名来控制两个进程之间的控制流。


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

< P>扩展ChrisG的思想,有点考虑使用Purrest.MistWindow句柄,并查看窗口消息循环是否响应。使用p/调用此Win32 api:。 从该链接:

如果函数成功,则返回 值为非零。SendMessageTimeout 不提供有关的信息 个别窗口超时,如果 使用HWNDU广播

如果函数失败或超时,则返回值为0。得到 扩展错误信息,呼叫 GetLastError。如果GetLastError返回 错误\u超时,然后函数超时 出去


“ChrisG”的答案是正确的,但我们需要每次刷新MainWindowTitle,最好检查是否为空。。。。像这样:

var proc = Process.Start("popup.exe");
while (string.IsNullOrEmpty(proc.MainWindowTitle))
{
    System.Threading.Thread.Sleep(100);
    proc.Refresh();
}

首先:我知道这很古老,但仍然没有一个公认的答案,所以我的方法可能会帮助其他人。:)

我为解决这个问题所做的是:

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


我知道这不是一个非常干净的解决方案,但这是我能想到的唯一一个性能独立的解决方案。

这里是一个使用
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();
    }
应用程序

我用过这门课。在父进程上,创建一个命名的EventWaitHandle,将事件的初始状态设置为无信号。父进程阻塞,直到子进程调用该方法,将事件的状态更改为signaled,如下所示

父进程:

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();
            }
        }
    }
}
子进程:

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

namespace MyChildProcess
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                // Representing some time consuming work.
                Thread.Sleep(5000);

                EventWaitHandle.OpenExisting("CHILD_PROCESS_READY")
                    .Set();

                Process.GetProcessById(Convert.ToInt32(args[0]))
                    .WaitForExit();
            }
            catch (Exception exception)
            { }
        }
    }
}

您还可以通过以下方式检查启动的流程是否响应:
while(process.responding)

什么是“确保”呢?在popup.exe中必须运行特定的东西,对吗?如果是这样的话,等待它运行是不够的。你也可以控制popup.exe吗?意思是您可以向其添加代码以向正在运行的生成进程发出信号吗?在第一个代码片段中,您必须在
进程.WaitForExit()之前手动调用
进程.Start()
;否则将引发异常。请确保您了解WaitForInputIdle的实际功能@ta.speot.is换句话说。。。OP到底想要什么?@Basic这是一个参考网站,这个答案可能会被非OP的人阅读。@Eagle Eye我不确定我是否理解你的意思?ta.speoit.is(不是Q或A的OP)暗示该功能没有像广告所宣传的那样工作。我查看了文档,它似乎完全符合OP的要求。这会以何种方式降低网站对未来访问者的可用性?
而(!Process.getprocesss().Any(p=>p.Name==myName)){Thread.Sleep(100);}
为什么不
GetProcessesByName()
while(Process.getProcessByName(myName).Length==0){Thread.Sleep(100);}
虽然它可能在大部分时间都能工作,但正确的方法是等到n毫秒后,如果找不到进程,就退出循环。这正是我在搜索时希望找到的结果。谢谢。我们能假设一个命令行应用程序获得标题后它就启动了吗?我添加了一个额外的签入while语句:!proc.hasexited尽管如此,它似乎是获取所需信息的最直接的方法。调用
process.BeginOutputReadLine()
process.BeginErrorReadLine()
之后抛出一个异常,该异常清楚地表明该进程尚未完全初始化。这可能取决于您启动的进程。对于我的Java进程来说还可以,而您的Java进程可能需要更多的时间来完成它所需要的工作。但是你仍然可以使用s
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 ...
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();
            }
        }
    }
}
using System;
using System.Threading;
using System.Diagnostics;

namespace MyChildProcess
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                // Representing some time consuming work.
                Thread.Sleep(5000);

                EventWaitHandle.OpenExisting("CHILD_PROCESS_READY")
                    .Set();

                Process.GetProcessById(Convert.ToInt32(args[0]))
                    .WaitForExit();
            }
            catch (Exception exception)
            { }
        }
    }
}