在Process.Start完成之前不要执行下一行

时间:2017-06-12 10:12:49

标签: c#

我正在编写一个简单的C#控制台应用程序,它打开了四个Windows资源管理器实例,并使用Pinvoke的MoveWindow将它们放在屏幕上。我的问题是Process.Start命令似乎运行得太慢,MoveWindow函数无法找到进程,除非我故意放慢程序速度。这是我的代码:

Process.Start(new ProcessStartInfo()
{
    FileName = "explorer",
    Arguments = location,  //Defined elsewhere (for testing just ".")
    UseShellExecute = false
});
int[] pos = GetPositions(position); //Little function which gets the positions I want for this window
System.Threading.Thread.Sleep(500);
IntPtr hnd = GetForegroundWindow();
bool ok = MoveWindow(hnd, pos[0], pos[1], pos[2], pos[3], false);

了解我如何({1}}获得(任意)半秒。它并不理想,因为我不知道它将运行的机器的规格。它可能最终在快速机器上效率低下,或者可能在较慢的机器上中断。是否有一种更具体的方式等待,直到一个过程开始,我不必任意等待一段时间?

另外,在一个半相关的注释中,您可能会注意到一些牛仔代码,它只是获取前景窗口来抓住我想要移动的窗口。这是因为我有一个绝对的母马试图挑选出特定的Window Explorer进程。从我可以告诉他们只是不像其他任何东西一样工作(比如当我用记事本或IE测试时)并且只是传递一个句柄不起作用。任何熟悉这个问题的人都可以随时做出贡献,但如果不是不花时间在它上面 - 这个解决方案很笨重,它可以工作,而且对于一点点应用我不想花费数小时时间来反击键盘试图找出正确的方法。

2 个答案:

答案 0 :(得分:2)

理论上,您可以调用Process.WaitForInputIdle()等待创建消息循环并在新启动的进程中启动并运行。但是,这不适用于所有应用程序(很可能不适用于Windows资源管理器)。

一个便宜的技巧是轮询要创建的进程的主窗口(source):

public static bool WaitForMainWindow(this Process process)
{
    while (!process.HasExited && process.MainWindowHandle == IntPtr.Zero)
    {
        Thread.Sleep(10);
    }

    return !process.HasExited;
}

您可能希望通过添加超时来使其更加健壮:

public static bool WaitForMainWindow(this Process process, uint timeout)
{
    var start = DateTime.Now;
    while (!process.HasExited && process.MainWindowHandle == IntPtr.Zero)
    {
        Thread.Sleep(10);
        if ((DateTime.Now - start).TotalMilliseconds >= timeout)
        {
            return false;
        }
    }

    return !process.HasExited;
}

答案 1 :(得分:0)

您可以尝试这样的事情

while(!process.HasExited)
{
  //process running
}
//Done