windows 如何等待资源管理器窗口打开完毕?

vngu2lb8  于 2023-03-09  发布在  Windows
关注(0)|答案(2)|浏览(324)

完整再现示例(.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.");
    }
}

实际行为:消息框显示。几秒钟后,资源管理器窗口在消息框前面打开,从而隐藏消息。
预期行为:代码一直等到资源管理器窗口可见(这正是我期望WaitForInputIdle做的),然后在资源管理器窗口前面显示消息框。
我已经尝试过的

  • 如果我激活代码示例中的Thread.Sleep语句,它就可以工作(即,我得到了所需的行为)。我不喜欢这种解决方案,因为在我的计算机和客户的计算机上打开资源管理器窗口所需的时间可能不同。
  • 我尝试了各种ProcessStartInfo选项的各种组合(UseShellExecuteWindowStyleCreateNoWindow),但没有效果。请注意,我不想隐藏资源管理器窗口,我只想等到它可见。
  • 我知道我可以使用SetForegroundWindow使我的进程成为最前面的窗口,但这没有帮助。这是:(a)显然没有必要(Thread-Sleep-variant没有它也能工作);(B)我需要在资源管理器窗口打开 * 之后 * 才能这样做,以防止资源管理器窗口再次“窃取”前景,从而导致我最初的问题。
  • 我还尝试在循环中检查p.MainWindowTitle,但即使窗口打开(或进程退出)后,该值仍为空。显然,新的资源管理器窗口 * 实际上 * 由与我启动的进程不同的进程拥有。
  • 我知道我可以使用Windows API方法FindWindowEnumWindows来找出是否存在具有该文件夹名称的 * 任何 * 窗口,但这(a)工作量很大,(b)不太优雅。

我是不是错过了一个显而易见的正确答案?

ctehm74n

ctehm74n1#

您可以在此处找到问题的解决方案: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.");
nhjlsmyf

nhjlsmyf2#

恐怕你得用不太文雅的方式了。
如果您尝试:

var p = Process.Start("explorer.exe", @"C:\Windows");
p.WaitForExit();
MessageBox.Show("Explorer window has opened.");

你会发现消息框仍然显示,这意味着你看到的窗口不属于你创建的进程。有一个默认的资源管理器进程时,Windows启动,新的资源管理器进程似乎喜欢寻找默认的,让它创建一个新的窗口。有一个选项称为“启动文件夹窗口在一个单独的进程”,不幸的是,经过我的测试,这个选项现在不工作。

相关问题