【问题标题】:Sending WM_COPY from a Delphi app. to another process in Windows 7从 Delphi 应用程序发送 WM_COPY。到 Windows 7 中的另一个进程
【发布时间】:2023-03-17 05:50:01
【问题描述】:

我有一个 Delphi (BDS 2006) 应用程序,它将击键发送到 QuickBooks 会计软件以遍历 QuickBooks 表单(发票),将文本从当前编辑控件复制到 Windows 剪贴板(以收集数据),根据收集数据,最后通过发送击键将结果写入表单。

这个应用程序已经开发了很多年,使用了广泛的(至少对我而言)Windows API 技术来识别前景窗口、焦点窗口等,并被全球数十个用户使用......我只是告诉你它可以在很多系统上工作的证据。

但不是全部。最近我收到很多关于 Windows 7 系统的故障报告(QuickBooks 的版本似乎无关紧要)。发送给报告问题的客户的调试版本表明它没有将任何内容复制到剪贴板——尽管它似乎仍然能够执行其他所有操作(发送击键以遍历表单,并击键以粘贴计算结果...不幸的是,现在总是为零,因为没有收集到数据。)

这是我用来向 QuickBooks 中的编辑控制窗口发送 WM_COPY 消息的代码。 (在 XP 或 Windows 7 系统上,我们不能让此代码在此处失败 - 但它不适用于多个用户。)

var
  iResult : DWORD;
begin
  ...
      //Edit control has the focus on the QB form, so try to copy its contents
  if SendMessageTimeout(Wnd, WM_COPY, 0, 0,
      SMTO_ABORTIFHUNG or SMTO_NORMAL,
      2000,
      iResult) = 0 then begin                 //0 = Failed or timed out

        //NOTE:  Users DO NOT get the following message--the 
        //SendMessageTimeout() simply returns without error, as if the 
        //WM_COPY is being sent correctly.

    ShowMessage('SendMessageTimeout FAILED');
    Abort;    
  end;

            //At this point, the clipboard has nothing on it, on users'
            //machines where it fails to work.
  ...   
end;

不想让我们向其发送调试版本的最终用户失去耐心,我正在寻找想法,然后再发送任何其他内容供他们尝试/测试...

注意事项/问题:

  • 所有其他击键都是通过 SendInput 发送的,它们工作正常。我相信我们出于速度原因开始使用 SendMessageTimeout(WM_COPY) 而不是发送 Ctrl-C 作为击键 - 它允许我们在返回时立即访问剪贴板,而不是等待 Ctrl-C 的未知/无限时间由 QuickBooks 处理。

  • 我相信我们已经要求用户在我们的应用程序上尝试 RunAs...Administrator,但这没有任何效果(我必须验证是否已完成)。

  • 我想知道问题是否是由于 UAC 冲突引起的?我们的应用程序目前没有数字签名,也没有使用清单。我一直在阅读有关在其中添加带有 UIAccess=True 的清单的信息。但是,如果我们的应用程序已经可以毫无问题地向 QuickBooks 发送击键,那么设置 UIAccess=True 是否会对允许 SendMessageTimeout() 成功产生任何影响?我需要使用数字证书吗?让 UIAccess 设置生效?

  • 如果在清单中没有数字签名和 UIAccess 的情况下 SendMessage 将无法工作,我们是否可以退回以发送 Ctrl-C 作为击键? (我不这么认为;微软肯定不会允许围绕安全概念进行这种最终运行。)

我会很感激任何 cmets 来理顺我的想法......

【问题讨论】:

  • 也许是一个愚蠢的问题,但如果你有一个编辑控件,并且想知道它包含什么,发送WM_GETTEXTLENGTH/WM_GETTEXT而不是让它复制它不是更容易吗?内容到剪贴板?
  • 是的,如果您使用“uiAccess=true”,您必须对可执行文件进行数字签名。这是否能解决问题,我不知道。
  • 我同意 hvd 的观点,即使用 wm_getText 会更简洁。至于手头的问题,是不是因为某种未知的原因没有在你要发送消息的文本框中选择文本?
  • 就像一个评论:你为什么要求助于这个而不是使用已发布的 QuickBooks API?它有一种基于 XML 的方式将信息传入和传出 QuickBooks 到其他应用程序,而且它不那么笨拙,需要跳过的障碍也少得多。它至少从 2000 年就已经存在了。我参与了早期的测试,并实际编写了一个应用程序(为我的一个客户),当时通过 QB 应用程序商店出售。
  • 客户端运行 QuickBooks 提升了吗?

标签: delphi windows-7 manifest uac sendinput


【解决方案1】:

这可能与“用户界面特权隔离”(UIPI) 而不是 UAC 有关。检查每个进程的完整性级别。不允许低完整性进程向高完整性进程发送窗口消息,除非高完整性进程通过调用ChangeWindowMessageFilter/Ex() 明确允许。

【讨论】:

  • 如果是访问权限问题,SendMessageTimeout 调用不会失败吗?
  • @500 - 我不这么认为;我相信它只会返回 0(从我今天读到的内容)。
  • @Remy - 所以在这种情况下,如果我理解的话,解决方案是对我的应用程序进行数字签名,在清单中包含 UIAccess=True,并强制访问受限的用户查看 UAC 提升提示?如果是这样,他们将不会欣赏它(感谢 Microsoft),因为该应用程序通常在网络配置中运行。超过 5 个用户...其中大多数是标准用户。
  • @Mark Wilsdorf 您可以尝试发送 Ctrl-C 而不是使 UIAccess=True。
  • 顺便说一下,如果从受信任的位置运行,带有 UIAccess=True 的数字签名应用程序不会触发任何 UAC 提示。
【解决方案2】:

你能检查这个系统的 Internet Explorer Skype 插件吗(IE-选项-程序-附加组件)。这个插件有一个错误版本,会在剪贴板上弄乱数据。如果已安装此插件,请移除并测试。

【讨论】:

    猜你喜欢
    • 2012-03-29
    • 2014-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多