完整的重现示例(.NET Framework 4.8 控制台应用程序,Windows 10):
using System.Diagnostics;
using System.Windows.Forms;
static class Program
{
static void Main()
{
var p = Process.Start("explorer.exe", @"C:\Windows");
p.WaitForInputIdle();
// Thread.Sleep(5000);
MessageBox.Show("Explorer window has opened.");
}
}
实际行为:显示消息框。几秒钟后,资源管理器窗口在消息框前面打开,从而隐藏消息。
Desired behavior:代码一直等到 Explorer 窗口可见(这是我期望
WaitForInputIdle
做的),然后在 Explorer 窗口前面显示消息框。
我已经尝试过的:
Thread.Sleep
语句,它将起作用(即,我得到了期望的行为)。我不喜欢那个解决方案,因为打开资源管理器窗口需要时间
在我的电脑和我客户的电脑上可能会有所不同。ProcessStartInfo
选项的各种组合(UseShellExecute
,WindowStyle
,CreateNoWindow
),但没有任何区别。请注意,我不想隐藏资源管理器窗口,我只想等到它可见。SetForegroundWindow
使我的进程成为最重要的窗口。那没有帮助。它(a)显然没有必要(Thread-Sleep-variant 在没有它的情况下工作)和(b)我需要这样做afterExplorer 窗口完成打开以防止 Explorer 窗口再次“窃取”前景,回到我原来的问题。p.MainWindowTitle
,但即使在窗口打开(或进程退出)后该值仍然为空。显然,新的资源管理器窗口实际上由与我启动的进程不同的进程拥有。FindWindow
或 EnumWindows
来查明是否存在带有文件夹名称的 any 窗口,但那是 (a) 很多工作,并且 (b) 不是很优雅.我错过了一个明显的、正确的解决方案吗?
您可以在这里找到问题的解决方案:https://stackoverflow.com/a/35789386/18486478.
我还发现使用
Responding
变量更干净。
var p = Process.Start("explorer.exe", @"C:\Windows");
while (!p.Responding)
{
Thread.Sleep(1);
p.Refresh();
}
p.WaitForInputIdle();
MessageBox.Show("Explorer window has opened.");
恐怕你必须使用不太优雅的方式。
如果你尝试:
var p = Process.Start("explorer.exe", @"C:\Windows");
p.WaitForExit();
MessageBox.Show("Explorer window has opened.");
您会发现消息框仍然显示,这意味着您看到的窗口不属于您创建的进程。 Windows启动时有一个默认的资源管理器进程,新的资源管理器进程似乎喜欢寻找默认的资源管理器并让它创建一个新窗口。有一个名为“在单独的进程中启动文件夹窗口”的选项,不幸的是,经过我的测试,这个选项现在不起作用。