从Delphi应用程序发送WM_副本。到Windows 7中的另一个进程

从Delphi应用程序发送WM_副本。到Windows 7中的另一个进程,delphi,windows-7,manifest,uac,sendinput,Delphi,Windows 7,Manifest,Uac,Sendinput,我有一个Delphi BDS 2006应用程序,它向QuickBooks会计软件发送击键,以遍历QuickBooks表单发票,将当前编辑控件中的文本复制到Windows剪贴板以收集数据,根据收集的数据进行一些计算,最后通过发送击键将结果写入表单 这个应用程序已经开发了很多年,使用了广泛的Windows API技术来识别前景窗口、聚焦窗口等,并且被全世界几十个用户使用……我只告诉你,这是它在很多系统上工作的证据 但并非全部。最近我收到了很多失败的报告,在Windows7系统上,QuickBooks

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

这个应用程序已经开发了很多年,使用了广泛的Windows API技术来识别前景窗口、聚焦窗口等,并且被全世界几十个用户使用……我只告诉你,这是它在很多系统上工作的证据

但并非全部。最近我收到了很多失败的报告,在Windows7系统上,QuickBooks的版本似乎并不重要。发送给报告问题的客户的调试版本显示,它没有将任何内容复制到剪贴板,尽管它似乎仍然能够执行其他所有操作发送击键以遍历表单,并将击键粘贴到计算结果中……不幸的是,由于未收集到任何数据,现在的结果始终为零

下面是我用来向QuickBooks中的编辑控制窗口发送WM_COPY消息的代码。我们不能让这段代码在XP或Windows7系统上失败,但它不适用于多个用户

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发送的,它们工作正常。我相信我们开始使用SendMessageTimeoutHM\u COPY,而不是将Ctrl-C作为按键发送,因为速度原因,它允许我们在返回时立即访问剪贴板,而不是等待未知/不确定的时间,等待QuickBooks处理Ctrl-C

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

我想知道问题是否是由于UAC冲突造成的?我们的应用程序当前没有数字签名,并且没有使用清单。我一直在阅读有关添加UIAccess=True的清单的内容。但是,如果我们的应用程序可以毫无问题地向QuickBooks发送击键,那么设置UIAccess=True是否会影响SendMessageTimeout的成功?我是否需要使用数字证书才能使UIAccess设置生效

如果清单中没有数字签名&UIAccess,SendMessage将无法工作,那么我们是否可以退回到以击键方式发送Ctrl-C?我不这么认为;微软肯定不会允许这种结局围绕着一个安全概念


如果您能给我提些建议来理顺我的思路,我将不胜感激。

这可能与用户界面特权隔离UIPI而不是UAC有关。检查每个流程的完整性级别。不允许较低完整性进程向较高完整性进程发送窗口消息,除非较高完整性进程通过调用ChangeWindowMessageFilter/Ex明确允许。这可能与用户界面权限隔离UIPI而不是UAC有关。检查每个流程的完整性级别。不允许较低完整性进程向较高完整性进程发送窗口消息,除非较高完整性进程通过调用ChangeWindowMessageFilter/Ex明确允许。您是否可以签入此系统Skype插件以获取Internet Explorer IE选项程序加载项。这个插件有一个错误版本,它会把剪贴板上的数据弄乱。如果已安装此插件,请删除并测试。

您是否可以签入此系统Skype插件以用于Internet Explorer IE选项程序加载项。这个插件有一个错误版本,它会把剪贴板上的数据弄乱。如果安装了此插件,请删除并测试。

这可能是一个愚蠢的问题,但是如果您有一个编辑控件,并且希望知道它包含什么,那么发送WM_GETTEXTLENGTH/WM_GETTEXT而不是让它将其内容复制到剪贴板不是更容易吗?是的,如果使用uiAccess=true,您必须对可执行文件进行数字签名。我不知道这是否能解决这个问题。我同意hvd的观点,使用wm_getText会更干净。至于手头的问题,可能是由于某种未知的原因,在您发送消息的文本框中没有选择文本吗?作为一个注释:为什么您要使用此选项而不是使用已发布的QuickBooks API?它有一种基于XML的方式,可以将信息从QuickBook传输到其他应用程序中,也可以将信息从QuickBook传输到其他应用程序中,这样就不那么麻烦了,需要跨越的障碍也少了很多。它至少从2000年就存在了;我参与了早期测试,实际上为我的一个客户编写了一个应用程序,当时通过QB应用程序商店出售。该客户程序是否运行QuickBooks?也许是个愚蠢的问题,但如果你有编辑控件,那么

h要知道它包含什么,发送WM_GETTEXTLENGTH/WM_GETTEXT而不是让它将其内容复制到剪贴板不是更容易吗?是的,如果使用uiAccess=true,则必须对可执行文件进行数字签名。我不知道这是否能解决这个问题。我同意hvd的观点,使用wm_getText会更干净。至于手头的问题,可能是由于某种未知的原因,在您发送消息的文本框中没有选择文本吗?作为一个注释:为什么您要使用此选项而不是使用已发布的QuickBooks API?它有一种基于XML的方式,可以将信息从QuickBook传输到其他应用程序中,也可以将信息从QuickBook传输到其他应用程序中,这样就不那么麻烦了,需要跨越的障碍也少了很多。它至少从2000年就存在了;我参与了早期测试,实际上为我的一个客户编写了一个应用程序,当时通过QB应用商店出售。该客户是否运行QuickBooks?如果是访问权限问题,SendMessageTimeout调用不会失败吗?@500-我不这么认为;我相信它只会从我今天读到的内容返回0。@Remy-那么,如果我理解的话,那么在这种情况下,解决方案是对我的应用程序进行数字签名,在清单中包含UIAccess=True,并强制受限访问用户查看UAC提升提示?如果是这样的话,他们将不会感激微软,因为应用程序通常在网络配置中运行。在5个以上的用户中,大多数是标准用户。@Mark Wilsdorf您可以尝试发送Ctrl-C,而不是使UIAccess=True。顺便说一句,UIAccess=True的数字签名应用程序在可信位置运行时不会触发任何UAC提示。如果是访问权限问题,SendMessageTimeout调用不会失败吗?@500-我不这么认为;我相信它只会从我今天读到的内容返回0。@Remy-那么,如果我理解的话,那么在这种情况下,解决方案是对我的应用程序进行数字签名,在清单中包含UIAccess=True,并强制受限访问用户查看UAC提升提示?如果是这样的话,他们将不会感激微软,因为应用程序通常在网络配置中运行。5个以上的用户中,大多数是标准用户。@Mark Wilsdorf您可以尝试发送Ctrl-C,而不是使UIAccess=True。顺便说一句,UIAccess=True的数字签名应用程序如果从受信任的位置运行,将不会触发任何UAC提示。