该语句是:
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.WaitForExit()
之前手动调用 process.Start()
;否则会抛出异常。 - Bala R我也曾经需要过这个,然后我对进程的窗口标题进行了检查。如果它是你期望的那个,你就可以确定该应用正在运行。我检查的应用需要一些启动时间,这种方法对我很有效。
var process = Process.Start("popup.exe");
while(process.MainWindowTitle != "Title")
{
Thread.Sleep(10);
}
proc.Refresh();
,就像 @AlirezaNaghizadeh 提到的那样。 - user1127860'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()
。
我知道这不是一个很干净的解决方案,但这是我能想到的唯一一个应该与性能无关的解决方案。
process.BeginOutputReadLine()
或 Process.BeginErrorReadLine()
之后会抛出一个异常,明确指出进程尚未完全初始化。 - sɐunıɔןɐqɐp像其他人已经说过的那样,你的问题并不是立即显而易见的。我假设你想启动一个进程,并在“准备就绪”后执行另一个操作。
当然,“准备就绪”是关键。根据您的需求,简单等待可能足够。但是,如果您需要更强大的解决方案,可以考虑使用命名的Mutex来控制两个进程之间的控制流。
例如,在主进程中,您可以创建一个命名互斥体并启动一个线程或任务来等待。然后,您可以启动第二个进程。当该进程决定“准备就绪”时,它可以打开命名互斥体(当然,必须使用相同的名称)并向第一个进程发出信号。
我同意Tom的观点。此外,在执行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); }
- dss539GetProcessesByName()
呢?while(Process.GetProcessesByName(myName).Length == 0) { Thread.Sleep(100); }
。虽然这段代码大部分时间可行,但正确的方式是等待 n 毫秒并在未找到进程时跳出循环。 - Jack你确定Start
方法在子进程启动之前就返回了吗?我一直以为Start
是同步启动子进程的。
如果你想等待子进程完成某种初始化,那么你需要进行进程间通信 - 参见C#中Windows的进程间通信(.NET 2.0)。
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)
{ }
}
}
}
为了扩展@ChrisG的想法,可以考虑使用process.MainWindowHandle并查看窗口消息循环是否响应。使用p/invoke这个Win32 api: SendMessageTimeout。 从该链接中得到:
如果函数成功,则返回值为非零。如果使用HWND_BROADCAST,则SendMessageTimeout不提供有关单个窗口超时的信息。
如果函数失败或超时,则返回值为0。要获取扩展错误信息,请调用GetLastError。如果GetLastError返回ERROR_TIMEOUT,则函数已超时。
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();
}