WaitForInputIdle 不适用于以编程方式启动 mspaint [英] WaitForInputIdle doesn't work for starting mspaint programmatically

查看:30
本文介绍了WaitForInputIdle 不适用于以编程方式启动 mspaint的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试打开mspaint"并在它初始化后立即找到它的句柄.但是如果我调用 WaitForInputIdleFindWindow 返回 NULL.如果我尝试使用 Sleep(1000) 函数,它会起作用.但我认为等待程序准备就绪不是正确的方法.此代码有解决方案吗?

I'm trying to open "mspaint" and find handle of it right after it has been initialized. But FindWindow returns NULL if I call WaitForInputIdle. If I try to use the function Sleep(1000) it works. But I don't think it's a right way to wait for the program to be ready. Is there a solution for this code?

    CString strWindowDirectory;
    GetSystemDirectory(strWindowDirectory.GetBuffer(MAX_PATH), MAX_PATH);
    SHELLEXECUTEINFO sei = { 0 };
    sei.cbSize = sizeof(SHELLEXECUTEINFO);
    sei.fMask =  SEE_MASK_NOCLOSEPROCESS;
    sei.lpVerb = L"open";
    sei.lpFile = L"mspaint";
    sei.lpDirectory = strWindowDirectory;
    sei.nShow = SW_SHOWNORMAL;

    HWND    hPaint = NULL;
    if(ShellExecuteEx(&sei))
    {
        int r = ::WaitForInputIdle(sei.hProcess, INFINITE);
        ATLTRACE(L"WaitForInputIdle %d
", r);

        if (sei.hProcess == NULL)       return;

        hPaint = ::FindWindow(L"MSPaintApp", NULL); 

        ATLTRACE(L"Handle %d
", hPaint);
        if (!hPaint) return;
    }
    else
    {
        MessageBox(L"Couldn't find mspaint program");
        return;
    }

推荐答案

WaitForInputIdle 有效,但不是您假设的那样.这主要是因为文档具有误导性(或至少没有应有的明确):

WaitForInputIdle works, but not the way you assume it does. This is largely, because the documentation is misleading (or at least not as explicit as it should be):

等待指定进程完成其初始输入的处理并等待用户输入且没有待处理的输入,或者直到超时间隔已过.

Waits until the specified process has finished processing its initial input and is waiting for user input with no input pending, or until the time-out interval has elapsed.

这在刑事上几乎是不准确的.虽然备注 部分指出,WaitForInputIdle 每个进程最多等待一次,但它从未提及重要的细节.具体:

This is almost criminally inaccurate. While the Remarks section notes, that WaitForInputIdle waits at most once per process, it never mentions significant details. Specifically:

  • WaitForInputIdle 返回,一旦初始启动达到某个点,进程中的任何线程都准备好处理消息.这些消息不需要是用户输入.
  • WaitForInputIdle 的发明是为了允许进程使用基于消息的协议与子进程通信.解决的具体情况是 DDE,没有人1) 不再使用.
  • WaitForInputIdle returns, as soon as the initial startup has come to a point, where any thread in the process is ready to process messages. Those messages need not be user input.
  • WaitForInputIdle was invented to allow a process to communicate with a child process using a message-based protocol. The specific scenario addressed was DDE, which no one1) uses anymore.

WaitForInputIdle 不能用作解决您的问题的可靠解决方案:等待子进程的 UI 出现.你真的需要等待 UI 出现.

WaitForInputIdle cannot be used as a reliable solution to your problem: Waiting for a child process' UI to show up. You really need to wait for the UI show up.

系统提供了两种解决方案供您使用:

The system offers two solutions you can use:

  1. 全球CBT hook,然后等待对于 HCBT_CREATEWND 回调.您可以检查CREATESTRUCTlpszClass 和/或 lpszName 成员过滤掉您感兴趣的窗口.
  2. 使用 WinEvents 并响应 <代码>EVENT_OBJECT_CREATE 事件.
  1. A global CBT hook, and wait for the HCBT_CREATEWND callback. You can inspect the CREATESTRUCT's lpszClass and/or lpszName members to filter out the window you are interested in.
  2. Use WinEvents and respond to the EVENT_OBJECT_CREATE event.

每当要创建窗口时,都会调用全局 CBT 钩子.HWND 引用的内核结构已完全填充,但调用 CreateWindow[Ex] 的客户端可能仍会终止窗口创建.相比之下,WinEvent 是在窗口完全构建完成并准备好进行交互后发出的.

The global CBT hook is called, whenever a window is about to be created. The kernel structures that the HWND references have been fully populated, but the client calling CreateWindow[Ex] may still terminate window creation. In contrast, the WinEvent is issued, after the window has been fully constructed, and is ready for interaction.

通常,当应用程序需要在 CreateWindowEx 的调用者看到 HWND 之前更新窗口的某些方面时,使用基于 CBT 钩子的解决方案> 第一次.相反,WinEvents 通常是实施辅助功能或 UI 自动化解决方案时的首选工具.

In general, a solution based on a CBT hook is used, when an application needs to update certain aspects of a window before the caller of CreateWindowEx gets to see the HWND for the first time. WinEvents, instead, are usually the tool of choice when implementing accessibility or UI automation solutions.


其他资源:


1) 是的,我知道,某些应用程序可能仍在使用 DDE.但是如果 Raymond Chen 在 2007 年建议,我们应该随时停止使用 DDE,我只是将其作为权威指导传递.


1) Yes, I know, some applications might still use DDE. But if Raymond Chen suggested in 2007, that we should feel free to stop using DDE, I'll just pass that on as authoritative guidance.

这篇关于WaitForInputIdle 不适用于以编程方式启动 mspaint的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆