【问题标题】:WinAPI EM_STREAMOUT crashWinAPI EM_STREAMOUT 崩溃
【发布时间】:2014-02-22 23:03:33
【问题描述】:

我正在尝试从另一个程序中获取 Richedit 控件的文本。

所以我为 SendMessage 找到了 EM_STREAMOUT。

这是我目前的代码(也来自另一个 Stackoverflow 主题):

    DWORD CALLBACK EditStreamOutCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
    std::stringstream *rtf = (std::stringstream*) dwCookie;
    rtf->write((char*)pbBuff, cb);
    *pcb = cb;
    return 0;
}

int main() {
    std::stringstream rtf;

    EDITSTREAM es = {0};
    es.dwCookie = (DWORD_PTR) &rtf;
    es.pfnCallback = &EditStreamOutCallback;
    SendMessage((HWND) 0x00000000000A06E8, EM_STREAMOUT, SF_RTF, (LPARAM)&es);

}

唯一发生的事情是 SendMessage 返回 0 - 所以显然没有读取任何字节 - 我试图从中获取信息的程序的 CPU 使用率达到 100%。

【问题讨论】:

  • EM_STREAMOUT 无法跨越进程边界。您需要将代码注入其他进程才能使其正常工作。
  • 但是使用 WM_GETTEXT 从普通编辑控件中读取文本工作正常,我在 MSDN 中没有找到任何说明它不能跨进程边界工作的内容。
  • 您在 SO 评论中找到了它。没错。
  • 假设它是正确的 - 我如何从另一个程序的 Richedit 中获取文本?这一定是可能的,因为我能够在围绕 WinAPI 的 AutoIt 中做到这一点。
  • WM_GETTEXT 可以,但是如果你想要格式化文本,你必须注入你的代码。

标签: c++ c winapi sendmessage richedit


【解决方案1】:

某些消息,例如WM_GETTEXT,由 Windows 为您编组。这就是您可以跨进程边界检索窗口文本的原因。 EM_STREAMIN/OUT 不会自动封送。这就是您的代码崩溃的原因。 EDITSTREAM 结构和回调代码必须存在于拥有 RichEdit 的同一进程的地址空间中。

对于许多需要跨越进程边界的非编组消息,您可以使用VirtualAllocEx() 分配输入/输出缓冲区,使用WriteProcessMemory() 填充它们,并使用ReadProcessMemory() 从它们中读取。但是因为EDITSTREAM 回调代码也需要在同一个进程中,所以最好将整个EM_STREAMOUT 逻辑移动到一个DLL 中,然后使用CreateRemoteThread() 或其他注入技术将其注入目标进程。您可以使用GetWindowThreadProcessId() 来获取拥有 RichEdit 的进程/线程 ID。然后,您的 DLL 可以使用您选择的任何 IPC(进程间通信)机制(例如命名管道、邮槽、WM_COPYDATA 消息等)检索 RichEdit 数据并将其发送回您的主应用程序。

【讨论】:

  • UIA 是否支持检索 RichEdit 的 RTF 而不是其纯文本?
  • 问题要求“RichEdit 控件的文本”。虽然 UI 自动化不允许直接访问 RTF,但它提供了查询文本属性(例如字体或颜色)的接口。
  • question 可能是文本,但 code 是 RTF。并且必须扫描文本查询以获取属性和范围以收集格式信息非常低效。
猜你喜欢
  • 1970-01-01
  • 2016-06-19
  • 2014-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-01
相关资源
最近更新 更多