在继续使用方法之前,我需要确保一个进程正在运行。
该语句是:
Process.Start("popup.exe");
您可以执行WAIT命令或对此值设置延迟吗?
在继续使用方法之前,我需要确保一个进程正在运行。
该语句是:
Process.Start("popup.exe");
您可以执行WAIT命令或对此值设置延迟吗?
Answers:
你是说等到完成了吗?然后使用Process.WaitForExit
:
var process = new Process {
StartInfo = new ProcessStartInfo {
FileName = "popup.exe"
}
};
process.Start();
process.WaitForExit();
另外,如果您正在等待进入消息循环的应用程序带有UI,则可以说:
process.Start();
process.WaitForInputIdle();
最后,如果以上两种方法均不适用,请在Thread.Sleep
合理的时间内使用:
process.Start();
Thread.Sleep(1000); // sleep for one second
process.Start()
之前process.WaitForExit()
; 否则将引发异常。
首先:我知道这已经很老了,但是仍然没有一个可以接受的答案,所以也许我的方法会对别人有所帮助。:)
为了解决这个问题,我要做的是:
process.Start();
while (true)
{
try
{
var time = process.StartTime;
break;
}
catch (Exception) {}
}
var time = process.StartTime
只要进程未启动,关联将引发异常。因此,一旦通过,可以安全地假定进程正在运行并进一步进行处理。我用它来等待Java进程启动,因为这需要一些时间。这样,它应该独立于应用程序正在运行的计算机,而不是使用Thread.Sleep()
。
我知道这不是一个很干净的解决方案,但是我想到的唯一一个应该与性能无关的解决方案。
就像其他人已经说过的那样,您要问的不是立即显而易见的。我将假设您要启动一个过程,然后在过程“准备就绪”时执行另一个操作。
当然,“准备好了”是棘手的。根据您的需求,您可能会发现只需等待就足够了。但是,如果您需要一个更强大的解决方案,则可以考虑使用命名的Mutex来控制两个进程之间的控制流。
例如,在您的主进程中,您可以创建一个命名的互斥锁并启动一个线程或将等待的任务。然后,您可以开始第二个过程。当该进程确定“就绪”时,它可以打开已命名的互斥锁(当然,您必须使用相同的名称)并向第一个进程发出信号。
我同意汤姆。另外,要在执行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
以同步启动子进程的印象。
如果要等到子进程完成某种初始化之后,则需要进行进程间通信-请参阅C#(.NET 2.0)中Windows的进程间通信。
为了扩展@ChrisG的想法,请考虑使用process.MainWindowHandle并查看窗口消息循环是否正在响应。使用p /调用此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();
}
我使用了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)
{ }
}
}
}
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 ...