Подтвердить что ты не робот

С# - Создание процесса. Начало до тех пор, пока процесс не начнется.

Мне нужно убедиться, что процесс запущен, прежде чем переходить к методу.

Утверждение:

Process.Start("popup.exe");

Вы можете выполнить команду WAIT или установить задержку для этого значения?

4b9b3361

Ответ 1

Вы имеете в виду подождать, пока это не закончится? Затем используйте Process.WaitForExit:

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

В качестве альтернативы, если это приложение с пользовательским интерфейсом, которое вы ожидаете ввести в цикл сообщений, вы можете сказать:

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

Наконец, если ни один из них не применяется, просто Thread.Sleep в течение некоторого разумного промежутка времени:

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

Ответ 2

Мне тоже понадобился этот раз, и я проверил заголовок окна процесса. Если это тот, который вы ожидаете, вы можете быть уверены, что приложение запущено. Приложению, которое я проверял, нужно некоторое время для запуска, и этот метод работал отлично для меня.

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

Ответ 3

Ответ "ChrisG" верен, но нам нужно обновлять MainWindowTitle каждый раз, и лучше проверить на пустое.... вот так:

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

Ответ 4

Прежде всего: я знаю, что это довольно старый, но до сих пор не принято ответа, поэтому, возможно, мой подход поможет кому-то другому.:)

Что я сделал для решения этой проблемы:

process.Start();

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

Ассоциация var time = process.StartTime выдаст исключение, пока процесс не запустится. Поэтому, как только это пройдет, можно с уверенностью предположить, что процесс запущен и работать с ним дальше. Я использую это, чтобы дождаться запуска Java-процесса, поскольку это занимает некоторое время. Таким образом, он должен быть независим от того, на какой машине работает приложение, а не на использовании Thread.Sleep().

Я понимаю, что это не очень чистое решение, но единственное, что должно быть независимым от производительности, о котором я мог подумать.

Ответ 5

Как уже говорили другие, не сразу видно, что вы просите. Я собираюсь предположить, что вы хотите начать процесс, а затем выполнить другое действие, когда процесс "готов".

Конечно, "готов" - это сложный бит. В зависимости от того, что вам нужно, вы можете обнаружить, что просто ждать достаточно. Однако, если вам нужно более надежное решение, вы можете использовать имя Mutex для управления потоком управления между двумя процессами.

Например, в вашем основном процессе вы можете создать именованный мьютекс и запустить поток или задачу, которые будут ждать. Затем вы можете запустить второй процесс. Когда этот процесс решает, что "он готов", он может открыть именованный мьютекс (вы должны, конечно, использовать одно и то же имя) и передать сигнал первому процессу.

Ответ 6

Я согласен с Томом. Кроме того, чтобы проверить процессы при выполнении Thread.Sleep, проверьте запущенные процессы. Что-то вроде:

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

    Thread.CurrentThread.Sleep(1000);
}

Ответ 7

Вы уверены, что метод Start возвращается до запуска дочернего процесса? Мне всегда казалось, что Start синхронно запускает дочерний процесс.

Если вы хотите подождать, пока ваш дочерний процесс завершит какую-то инициализацию, вам понадобится межпроцессная коммуникация - см. Interprocess communication для Windows на С# (.NET 2.0).

Ответ 8

Чтобы расширить идею @ChrisG, рассмотрите возможность использования process.MainWindowHandle и посмотрите, отвечает ли цикл окна сообщений. Используйте p/invoke this Win32 api: SendMessageTimeout. По этой ссылке:

Если функция завершается успешно, возвращение значение отличное от нуля. SendMessageTimeout не предоставляет информацию о отдельные окна выходят из строя, если Используется HWND_BROADCAST.

Если функция выйдет из строя или истечет время ожидания, возвращаемое значение равно 0. Чтобы получить расширенная информация об ошибках, вызов GetLastError. Если GetLastError возвращается ERROR_TIMEOUT, тогда функция timed из.

Ответ 9

Я думаю, что OP может ссылаться на необходимость иметь действительный дескриптор окна из дочернего процесса, чтобы он мог каким-то образом обработать его.

В моем случае я хочу создать Perl script для запуска в окне консоли DOS и центрировать окно в моем приложении форм при его запуске. Если я захвачу Process.MainWindowHandle слишком рано и назову "MoveWindow" на нем, дескриптор еще недействителен, и вызов ничего не делает. Если я жду второй (вызывая Thread.Wait(1000)), экран появляется в своем местоположении по умолчанию и внезапно перемещается через секунду. Либо может быть очень неприятно для пользователя.

Перейдя в цикл и ожидая, что "Process.MainWindowTitle" вернет что-то значимое, я могу захватить окно, как только оно реагирует, и сосредоточить его на моей форме без раздражающего мерцания.

OP может пытаться сделать что-то подобное.

Ответ 10

Здесь реализация, которая использует 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();
    }

Ответ 11

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

Ответ 12

Я использовал класс EventWaitHandle. В родительском процессе создайте именованный EventWaitHandle с начальным состоянием события, для которого задано отсутствие сигнала. Родительский процесс блокируется до тех пор, пока дочерний процесс не вызовет метод Set, изменив состояние события на сигнальное, как показано ниже.

Родительский процесс:

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