在 c# 中屏幕抓取 Windows 应用程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/375117/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 01:05:40  来源:igfitidea点击:

Screen-scraping a windows application in c#

c#.netscreen-scraping

提问by Tony Boarman

I need to scrape data from a windows application to run a query in another program. Does anyone know of a good starting point for me to do this in .NET?

我需要从 Windows 应用程序中抓取数据以在另一个程序中运行查询。有没有人知道我在 .NET 中做这件事的一个好的起点?

回答by HanClinto

You may want to look into the WM_GETTEXT message. This can be used to read text from other windows-- it's an archaic part of the Windows API, and if you're in C#, you'll need to p/invoke for it.

您可能需要查看WM_GETTEXT 消息。这可用于从其他窗口读取文本——它是 Windows API 的一个古老部分,如果您使用 C#,则需要对其进行 p/invoke。

Check out this pagefor an example of doing this in C#.

查看此页面以获取在 C# 中执行此操作的示例。

Basically, you first FindControlEx() to get the handle of the window that you want (by caption).

基本上,您首先通过 FindControlEx() 获取所需窗口的句柄(按标题)。

Second, you recursively enumerate the controls on that window with EnumChildWindows() to find all of the window's child controls, and all of those children's children until you have a complete map of the target form.

其次,您使用 EnumChildWindows() 递归枚举该窗口上的控件以查找窗口的所有子控件以及所有这些子控件的子控件,直到您拥有目标窗体的完整映射。

Here is a selected portion of Theta-ga's excellent explanationfrom Google Answers:

以下是来自 Google Answers的Theta-ga 出色解释的精选部分:

To get the contents of any textbox or listbox control, all we need is it's window handle. If you have already obtained the window handle then move to part 2 of the explaination.

要获取任何文本框或列表框控件的内容,我们只需要它的窗口句柄。如果您已经获得了窗口句柄,请移至说明的第 2 部分。

PART 1: Obtaining the control handle

第 1 部分:获取控制句柄

  • To obtain the handle of a control, we first obtain the handle of it?s parent window. We can do this by using the Win32 FindControlEx() method. This method takes in the window caption (such as 'Calculator') and/or its class name, and return its handle.
  • Once we have the parent window handle, we can call the Win32 EnumChildWindows method. This method takes in a callback method, which it calls with the handle of every child control it finds for the specified parent. For eg., if we call this method with the handle of the Calculator window, it will call the callback method with the handle of the textbox control, and then again with the handles of each of the buttons on the Calculator window, and so on.
  • Since we are only interested in the handle of the textbox control, we can check the class of the window in the callback method. The Win32 method GetClassName() can be used for this. This method takes in a window handle and provides us with a string containing the class name. So a textbox belongs to the ?Edit? class, a listbox to the 'ListBox' class and so on. Once you have determined that you have the handle for the right control, you can read its contents.
  • 要获取控件的句柄,我们首先要获取它的父窗口的句柄。我们可以通过使用 Win32 FindControlEx() 方法来做到这一点。此方法接受窗口标题(例如“计算器”)和/或其类名,并返回其句柄。
  • 一旦我们有了父窗口句柄,我们就可以调用 Win32 EnumChildWindows 方法。此方法接受一个回调方法,它使用它为指定父级找到的每个子控件的句柄调用该方法。例如,如果我们使用计算器窗口的句柄调用此方法,它将使用文本框控件的句柄调用回调方法,然后再次使用计算器窗口上的每个按钮的句柄,依此类推.
  • 由于我们只对文本框控件的句柄感兴趣,我们可以在回调方法中查看窗口的类。Win32 方法 GetClassName() 可用于此目的。这个方法接受一个窗口句柄并为我们提供一个包含类名的字符串。所以文本框属于 ?Edit? 类,“ListBox”类的列表框等等。一旦您确定您拥有正确控件的句柄,您就可以阅读其内容。

PART 2: Reading the contents of a control

第 2 部分:读取控件的内容

  • You can read in the contents of a control by using the Win32 SendMessage() function, and using it to pass the WM_GETTEXT message to the target control. This will give you the text content of the control. This method will work for a textbox, button, or static control.
  • However, the above approach will fail if you try to read the contents of a listbox. To get the contents of a listbox, we need to first use SendMessage() with the LB_GETCOUNT message to get the count of list items. Then we need to call SendMessage() with the LB_GETTEXT message for each item in the list.
  • 您可以使用 Win32 SendMessage() 函数读入控件的内容,并使用它来将 WM_GETTEXT 消息传递给目标控件。这将为您提供控件的文本内容。此方法适用于文本框、按钮或静态控件。
  • 但是,如果您尝试读取列表框的内容,上述方法将失败。要获取列表框的内容,我们需要首先使用带有 LB_GETCOUNT 消息的 SendMessage() 来获取列表项的计数。然后我们需要为列表中的每个项目使用 LB_GETTEXT 消息调用 SendMessage()。