Мені потрібно переконатися, що процес запущений, перш ніж переходити до методу.
Заява така:
Process.Start("popup.exe");
Чи можете ви виконати команду WAIT або встановити затримку цього значення?
Мені потрібно переконатися, що процес запущений, перш ніж переходити до методу.
Заява така:
Process.Start("popup.exe");
Чи можете ви виконати команду WAIT або встановити затримку цього значення?
Відповіді:
Ви маєте на увазі почекати, поки це буде зроблено? Потім використовуйте 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
process.Start()
раніше process.WaitForExit()
; інакше буде створено виняток.
Мені це теж потрібно було одного разу, і я перевірив назву вікна процесу. Якщо це той, який ви очікуєте, ви можете бути впевнені, що додаток запущений. Програмі, яку я перевіряв, знадобився певний час для запуску, і цей метод у мене справно працював.
var process = Process.Start("popup.exe");
while(process.MainWindowTitle != "Title")
{
Thread.Sleep(10);
}
Відповідь "ChrisG" правильна, але нам потрібно кожен раз оновлювати MainWindowTitle, і краще перевірити, чи немає порожніх .... ось так:
var proc = Process.Start("popup.exe");
while (string.IsNullOrEmpty(proc.MainWindowTitle))
{
System.Threading.Thread.Sleep(100);
proc.Refresh();
}
Перш за все: я знаю, що це досить давно, але досі немає прийнятої відповіді, тому, можливо, мій підхід допоможе комусь іншому. :)
Я вирішив це:
process.Start();
while (true)
{
try
{
var time = process.StartTime;
break;
}
catch (Exception) {}
}
Асоціація var time = process.StartTime
видасть виняток, якщо процес не розпочався. Отже, як тільки він пройде, можна буде припустити, що процес запущений, і працювати з ним далі. Я використовую це, щоб дочекатися запуску процесу Java, оскільки це займає деякий час. Таким чином, він повинен бути незалежним від того, на якій машині працює програма, а не використовує її Thread.Sleep()
.
Я розумію, що це не дуже чисте рішення, але єдине, яке повинно бути незалежним від продуктивності, я міг придумати.
Як вже говорили інші, не одразу очевидно, про що ви питаєте. Я збираюся припустити, що ви хочете запустити процес, а потім виконати іншу дію, коли процес "буде готовий".
Звичайно, "готово" - це складний шматок. Залежно від того, що вам потрібно, ви можете виявити, що достатньо простого очікування. Однак, якщо вам потрібно більш надійне рішення, ви можете розглянути можливість використання іменованого Mutex для управління потоком управління між вашими двома процесами.
Наприклад, у вашому основному процесі ви можете створити іменований мьютекс і запустити ланцюжок чи завдання, які будуть чекати. Потім ви можете розпочати 2-й процес. Коли цей процес вирішить, що "він готовий", він може відкрити названий мьютекс (звичайно, потрібно використовувати те саме ім'я) і подати сигнал першому процесу.
Я згоден з Томом. Крім того, щоб перевірити процеси під час виконання Thread.Sleep, перевірте запущені процеси. Щось на зразок:
bool found = 0;
while (!found)
{
foreach (Process clsProcess in Process.GetProcesses())
if (clsProcess.Name == Name)
found = true;
Thread.CurrentThread.Sleep(1000);
}
while (!Process.GetProcesses().Any(p=>p.Name == myName)) { Thread.Sleep(100); }
GetProcessesByName()
? while(Process.GetProcessesByName(myName).Length == 0) { Thread.Sleep(100); }
Хоча це може працювати більшу частину часу, правильним способом буде зачекати до n миль і вийти з циклу, якщо процес не буде знайдений.
Ви впевнені, що Start
метод повертається до початку дочірнього процесу? У мене завжди було враження, що Start
дитячий процес запускається синхронно.
Якщо ви хочете дочекатися, поки ваш дочірній процес завершить якусь ініціалізацію, вам знадобиться міжпроцесовий зв’язок - див. Розділ Міжпроцесовий зв’язок для Windows у C # (.NET 2.0) .
Щоб трохи розширити ідею @ ChrisG, розгляньте можливість використання process.MainWindowHandle та перевірити, чи відповідає цикл віконного повідомлення. Використовуйте p / викликати цей API Win32: SendMessageTimeout . За цим посиланням:
Якщо функція успішна, повертається значення ненульове. SendMessageTimeout не надає інформації про тайм-аут окремих вікон, якщо використовується HWND_BROADCAST.
Якщо функція виходить з ладу або закінчується час очікування, повертається значення 0. Щоб отримати розширену інформацію про помилку, зателефонуйте GetLastError. Якщо GetLastError повертає ERROR_TIMEOUT, тоді функція минула.
Я використовував клас 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)
{ }
}
}
}
Тут реалізація, яка використовує a 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();
}
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 ...
Ви також можете перевірити, чи запускається процес реагує чи ні, спробувавши щось подібне: while (process.responding)