如何在窗口中捕获数据

时间:2012-05-07 19:59:42

标签: c# windows

我的计算机上安装了桌面应用程序。当我启动一个程序时,某种窗口会被打开。让我们说,像这样(只是例子):

enter image description here

所以,我想用C#编写一个应用程序来找到这个窗口并从中捕获一些数据。

我应该看什么工具?我想走的是阻力最小的道路。

我需要从文本框中捕获图像,文本,还可以通过文本查找控件并单击它们。

5 个答案:

答案 0 :(得分:6)

我建议您使用这个很酷但鲜为人知的UI Automation API来完成这项工作。

为此,首先要测试的是启动相关的UISpy工具。它将在屏幕上显示所有可访问窗口的树。它还可以运行一些操作,例如按下菜单,选择项目等。这是使用所谓的UI Automation Control Patterns,它提供了一种分类和公开控件功能的方法,与控件类型或外观无关。控制。

因此,如果你可以使用UI Spy自动化这个应用程序,你也可以使用.NET代码做同样的事情(UISpy本身就是使用底层API)。

这是一篇关于UI自动化编程的有趣教程文章:The Microsoft UI Automation Library

答案 1 :(得分:2)

您应该开始枚举该进程的所有窗口的句柄:

https://stackoverflow.com/a/2584672/351383

然后为每个句柄获取有关文本和位置的信息,通过位置信息,您可以在该位置截取桌面的截图以获取图像AFAIK没有其他方法可以从正在运行的应用程序的窗口获取图像。

当您获得控件的屏幕位置时,请使用下面的链接模拟鼠标左键单击,搜索某些文本的窗口,然后单击控件内的某个点,这是点击某个点的方法:

https://stackoverflow.com/a/10355905/351383

我还给快速课程收集过程中的数据:

 public static class ProcessSpy
  {
    public static List<ProcessSpyData> GetDataForProcess(string processName)
    {
      var result = new List<ProcessSpyData>();
      Process myProc = Process.GetProcessesByName(processName).FirstOrDefault();
      if (myProc != null)
      {
        var myHandles = EnumerateProcessWindowHandles(myProc);
        foreach (IntPtr wndHandle in myHandles)
        {
          result.Add(new ProcessSpyData(wndHandle));
        }
      }
      return result;
    }

    delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);

    [DllImport("user32.dll")]
    static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);

    static IEnumerable<IntPtr> EnumerateProcessWindowHandles(Process prc)
    {
      var handles = new List<IntPtr>();

      foreach (ProcessThread thread in prc.Threads)
        EnumThreadWindows(thread.Id, (hWnd, lParam) => { handles.Add(hWnd); return true; }, IntPtr.Zero);

      return handles;
    }
  }

  public class ProcessSpyData
  {
    private const uint WM_GETTEXT = 0x000D;

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);

    [DllImport("user32.dll")]
    private static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);

    [StructLayout(LayoutKind.Sequential)]
    private struct RECT
    {
      int left, top, right, bottom;

      public Rectangle ToRectangle()
      {
        return new Rectangle(left, top, right - left, bottom - top);
      }
    }

    [DllImport("user32.dll")]
    static extern bool ClientToScreen(IntPtr hWnd, ref Point lpPoint);

    public IntPtr WindowHandle { get; private set; }
    public string WindowText { get; private set; }
    public Rectangle ClientRect { get; private set; }
    public Rectangle ScreenPos { get; private set; }

    public ProcessSpyData(IntPtr windowHandle)
    {
      this.WindowHandle = windowHandle;
      GetWindowText();
      GetWindowSize();
    }

    private void GetWindowText()
    {
      StringBuilder message = new StringBuilder(1024);
      SendMessage(this.WindowHandle, WM_GETTEXT, message.Capacity, message);
      this.WindowText = message.ToString();
    }

    private void GetWindowSize()
    {
      var nativeRect = new RECT();
      GetClientRect(this.WindowHandle, out nativeRect);
      this.ClientRect = nativeRect.ToRectangle();

      Point loc = this.ClientRect.Location;
      ClientToScreen(this.WindowHandle, ref loc);
      this.ScreenPos = new Rectangle(loc, this.ClientRect.Size);
    }
  }

这应该让你开始,但你必须知道如果应用程序使用非标准控件,那么使用此方法无法从中获取文本,对于图像,可能会在查看可执行资源时获得更好的结果

<强>更新

获取各种控件类型(MFC,winforms,Delphi VCL等)的控件文本将是非常艰巨的任务,但对于winforms看到优秀的Managed Windows API,他们甚至在{{3}中有某种间谍应用程序看看那个。

答案 2 :(得分:1)

您想要捕获哪种数据?

您可以尝试收听Windows消息或阅读内存。

答案 3 :(得分:0)

根据您将来要做的这些类型的任务有多少(或者这个任务有多重要),您可以尝试投资Ranorex Spy(Ranorex studio is ott)等。

链接:http://www.ranorex.com/product/tools/ranorex-spy.html

答案 4 :(得分:0)

除了注入要检查的应用程序之外别无他法。这就是UISpy的实际运行方式。这也是UISpy应该与管理凭证一起运行的原因。