C# - Making a Process.Start wait until the process has start-up

C#.NetWindowsProcess

C# Problem Overview


I need to make sure that a process is running before moving on with a method.

The statement is:

Process.Start("popup.exe");

Can you do a WAIT command or set a delay on this value?

C# Solutions


Solution 1 - C#

Do you mean wait until it's done? Then use Process.WaitForExit:

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

Alternatively, if it's an application with a UI that you are waiting to enter into a message loop, you can say:

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

Lastly, if neither of these apply, just Thread.Sleep for some reasonable amount of time:

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

Solution 2 - C#

I also needed this once, and I did a check on the window title of the process. If it is the one you expect, you can be sure the application is running. The application I was checking needed some time for startup and this method worked fine for me.

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

Solution 3 - C#

The answer of 'ChrisG' is correct, but we need to refresh MainWindowTitle every time and it's better to check for empty.... like this:

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

Solution 4 - C#

First of all: I know this is rather old but there still is not an accepted answer, so perhaps my approach will help someone else. :)

What I did to solve this is:

process.Start();

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

The association var time = process.StartTime will throw an exception as long as process did not start. So once it passes, it is safe to assume process is running and to work with it further. I am using this to wait for java process to start up, since it takes some time. This way it should be independent on what machine the application is running rather than using Thread.Sleep().

I understand this is not very clean solution, but the only one that should be performance independent I could think of.

Solution 5 - C#

Like others have already said, it's not immediately obvious what you're asking. I'm going to assume that you want to start a process and then perform another action when the process "is ready".

Of course, the "is ready" is the tricky bit. Depending on what you're needs are, you may find that simply waiting is sufficient. However, if you need a more robust solution, you can consider using a named Mutex to control the control flow between your two processes.

For example, in your main process, you might create a named mutex and start a thread or task which will wait. Then, you can start the 2nd process. When that process decides that "it is ready", it can open the named mutex (you have to use the same name, of course) and signal to the first process.

Solution 6 - C#

I agree with Tom. In addition, to check the processes while performing Thread.Sleep, check the running processes. Something like:

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

    Thread.CurrentThread.Sleep(1000);
}

Solution 7 - C#

Are you sure the Start method returns before the child process starts? I was always under the impression that Start starts the child process synchronously.

If you want to wait until your child process finishes some sort of initialization then you need inter-process communication - see https://stackoverflow.com/questions/50153.

Solution 8 - C#

I used the EventWaitHandle class. On the parent process, create a named EventWaitHandle with initial state of the event set to non-signaled. The parent process blocks until the child process calls the Set method, changing the state of the event to signaled, as shown below.

Parent Process:

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

Child Process:

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

Solution 9 - C#

To extend @ChrisG's idea, a little, consider using process.MainWindowHandle and seeing if the window message loop is responding. Use p/invoke this Win32 api: SendMessageTimeout. From that link:

> If the function succeeds, the return > value is nonzero. SendMessageTimeout > does not provide information about > individual windows timing out if > HWND_BROADCAST is used. > > If the function fails or times out, the return value is 0. To get > extended error information, call > GetLastError. If GetLastError returns > ERROR_TIMEOUT, then the function timed > out.

Solution 10 - C#

Here an implementation that uses a System.Threading.Timer. Maybe a bit much for its purpose.

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

Solution 11 - C#

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

}

App

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 ...

Solution 12 - C#

You can also check if the started process is responsive or not by trying something like this: while(process.responding)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTomView Question on Stackoverflow
Solution 1 - C#jasonView Answer on Stackoverflow
Solution 2 - C#ChrisGView Answer on Stackoverflow
Solution 3 - C#Alireza NaghizadehView Answer on Stackoverflow
Solution 4 - C#RhodryCZView Answer on Stackoverflow
Solution 5 - C#MattView Answer on Stackoverflow
Solution 6 - C#Frank PearsonView Answer on Stackoverflow
Solution 7 - C#Jakub KoneckiView Answer on Stackoverflow
Solution 8 - C#Roham AminiView Answer on Stackoverflow
Solution 9 - C#agent-jView Answer on Stackoverflow
Solution 10 - C#PeterView Answer on Stackoverflow
Solution 11 - C#Jason CView Answer on Stackoverflow
Solution 12 - C#Peter JacksonView Answer on Stackoverflow