繁体   English   中英

Process.Start with UseShellExecute 在前一个关闭窗口后无法将 notepad.exe 窗口带到前台

[英]Process.Start with UseShellExecute fails to bring notepad.exe window to the foreground after a previous close window

我正在尝试使用Process.Start (with UseShellExecute=true)来创建notepad.exe的实例。 下面的代码在另一个程序(语音输入程序)调用的 COM 对象内运行。

大多数情况下,代码运行良好,并按预期将记事本实例创建为具有焦点的新顶部窗口。 如果我使用 WM_CLOSE 消息关闭记事本窗口,我可以按预期的随机顺序打开、关闭和打开、打开、关闭、关闭记事本窗口,如下所示:

    Win32.PostMessage(Hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);

关闭记事本窗口的第二种方法

主流的第三方语音软件也提供了“关闭窗口”命令,当记事本处于前台时,它会关闭记事本窗口。 这种关闭记事本实例的方法是问题的一部分。

问题

问题是,在使用语音命令“关闭窗口”关闭记事本后,下一个打开操作会打开记事本,但不会将其带到前台。 它在 Outlook 或 Chrome 后面打开,并在任务栏上可见。 出于某种原因,在使用“关闭窗口”命令关闭记事本后, Process.Start代码不会将记事本实例带到前台。 我不明白为什么。 Process.Start代码应该不知道如何(或是否)关闭前一个记事本实例。

下面的代码尝试SetWindowPos强制记事本窗口到前景/顶部,以防Process.Start没有完成这项工作,但SetWindowPos代码永远不会失败,即使出现问题,也永远不会出现失败消息框。 (SetWindowPos 只是一个附带问题,因为该代码通常适用于 WM_CLOSE 消息。)

可在我的机器上重现

这是我在我的机器上登录的典型模式。 FChrome/FOutlook 表示 Chrome 或 Outlook 是实验的前景窗口(两者都尝试得到相同的结果)。 No = 记事本打开,Nc = 记事本关闭(如上),CW = “关闭窗口”,NoXX 表示失败(记事本没有出现在最上面的前景窗口)。

Sequences of operations: open, close, open, "close window", open (notepad open fails NoXX)
FChrome, No, Nc, No, CW, NoXX
FOutlook, No, Nc, No, CW, NoXX

有谁知道为什么窗口关闭方法(可能是 SendMessage 或 Win32.WindowDestroy?)会使Process.Start无法将记事本的新实例带到前台?

    // record name of foreground window before the operation
    var forehandle = GetForegroundWindow ();
    var forenamebefore = WinFuns.GetForegroundWindow ().Title;

    // create process to start notepad
    var psi = new ProcessStartInfo ();
    psi.UseShellExecute = true;
    psi.FileName = "notepad.exe";
    var proc = Process.Start (psi);
    Thread.Sleep (2000);

    // get foreground process name after Process.Start - it should be notepad
    proc.Refresh (); // refresh before retrieving the handle
    IntPtr prochandle = (IntPtr)proc.MainWindowHandle;
    var forenameafter = WinFuns.GetForegroundWindow ().Title;

    // get the process name of this code
    var myhandle = Process.GetCurrentProcess ().MainWindowHandle;
    var myname = (new WindowHandle (myhandle)).Title;

    // ensure the notepad instance is on top
    bool r;
    var p = new IntPtr (0);
    r = Win32.SetWindowPos (prochandle, p, 0, 0, 0, 0, 3); //window on top
    if (!r) MessageBox.Show ($"Failed to set top window position.");

    // show before/after/mynames after the operation is complete
    var msg = $"Foreground before: {forenamebefore}\n" +
              $"Foreground after: {forenameafter}\n" +
              $"My name is:       {myname}";
    MessageBox.Show (msg);

在又解决了这个问题几天并尝试了各种解决方案之后,我仍然无法解释为什么会出现原始问题(使用其他应用程序关闭记事本后未能将记事本置于最前面)。

但是,随着时间的推移,我的代码越来越大,因为我在每次 Win32 操作后检查每个 Win32 错误代码,并根据需要或适当的情况通过循环和重试来重试。

我的结论是,检查每个操作的每个 Win32 错误代码并每 100 毫秒重试失败的操作捕获了一些失败的操作,但没有解决原始问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM