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.
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);
}
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);
}
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.
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.
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.
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 ...
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)
{ }
}
}
}
Process process = Process.Start(@"MyApp.exe");
Process[] processes;
do
{
processes = Process.GetProcessesByName("MyApp");
Console.WriteLine("{0} Processes found.", processes.Length);
Thread.Sleep(1000);
}
while (processes.Length == 0);
Close(); // Or do whatever you want...