2017-06-12 34 views
2

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

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); 

看到我如何不必Sleep为(任意)半秒。这并不理想,因为我不知道它将运行的机器的规格。它可能最终会在一台快速机器上效率低下,或者在较慢的机器上崩溃。是否有更具体的方式等待一个过程开始,我不需要任意等待一段时间?


此外,在一个半相关的说明,您可能会注意到一点牛仔代码,只是让前台窗口抢我想移动的窗口。这是因为我有一个绝对的母马试图挑选出特定的Window Explorer进程。从我可以告诉他们只是没有像其他任何工作一样(就像我用记事本或IE测试时),只是传递句柄不起作用。任何熟悉这个问题的人都可以自由地贡献,但如果不是不花时间的话 - 这个解决方案很笨重,它可以工作,对于一个小应用我不想花费数小时的时间键盘试图找出正确的做法。

回答

0

你可以尝试这样的事情

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

问题在于,无论出于何种原因,显示的进程启动和Windows资源管理器窗口单独发生,如果我这样做,则无法找到句柄。无论如何,我不想做任何事情,直到一个进程退出,我只是想在可视化显示加载后执行一些操作,这似乎与Windows资源管理器在进程本身的不同时间表上运行。 –

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; 
} 
+0

当我尝试这个时,它总是返回false - 我相信因为MainWindowHandle总是为零(据我所知) –

相关问题