マシンにデスクトップ アプリケーションがインストールされています。プログラムを起動すると、ある種のウィンドウが開きます。たとえば、次のようなものです (単なる例):
そこで、このウィンドウを見つけてそこからデータを取得するアプリケーションを C# で作成したいと考えています。
どのツールを確認すればよいですか? 抵抗の少ない道を進みたい。
テキストボックスから画像やテキストをキャプチャし、テキストでコントロールを見つけてクリックする必要があります。
この作業には、クールだがあまり知られていないUI Automation APIを使用することをお勧めします。
このために、最初にテストすることは、関連するUISpyツールを起動することです。アクセス可能なすべてのウィンドウのツリーが画面に表示されます。また、メニューを押す、アイテムを選択するなどのアクションを実行することもできます。これは、UI オートメーション コントロール パターンと呼ばれるものを使用しており、コントロールの種類や外観に関係なく、コントロールの機能を分類して公開する方法を提供します。コントロール。
したがって、UI Spy を使用してこのアプリケーションを自動化できる場合は、.NET コードを使用してまったく同じことを行うこともできます (UISpy 自体は、基になる API を使用するだけです)。
UI オートメーション プログラミングに関する興味深いチュートリアル記事を次に示します。 Microsoft UI Automation Library
そのプロセスのすべてのウィンドウのハンドルの列挙を開始する必要があります。
https://stackoverflow.com/a/2584672/351383
次に、ハンドルごとにテキストと位置に関する情報を取得します。位置情報を使用すると、その位置でデスクトップのスクリーンショットを取得して画像を取得できます。実行中のアプリケーションのウィンドウから画像を取得する方法は他にありません。
コントロールの画面位置を取得したら、以下のリンクを使用してマウスの左クリックをシミュレートし、ウィンドウでテキストを検索してから、コントロール内のポイントをクリックします。ポイントをクリックする方法は次のとおりです。
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、winform、Delphi VCL など) のコントロール テキストを取得するのは非常に難しい作業ですが、winform については、優れたManaged Windows APIを参照してください。ツールにはある種のスパイ アプリケーションもあります。
どのような種類のデータを取得しようとしていますか?
Windows メッセージを聞いたり、メモリを読み取ったりしてみてください。
これらのタイプのタスクを将来どれだけ実行するか (またはこれがどれだけ重要か) に応じて、Ranorex Spy (Ranorex スタジオは ott) のようなものに投資することができます。
検査したいアプリケーションを注入する以外に方法はありません。これが実際に UISpy を実行する方法です。これは、UISpy を管理者資格情報で実行する必要がある理由でもあります。