web-dev-qa-db-ja.com

AutoItまたはWindows UIオートメーションを使用してアプリケーションのボタンをクリックする方法

セットアップ環境:

私はvb.netを使用して、.NET Framework 4でWindowsフォームアプリケーションを開発しています。


私の目標:

  1. Process.Startを使用してcalculator.exeを開きます
  2. すべてのvb.netコードを使用して、5 + 5 =をクリックできるようにします

SendKeysをメソッドとして使用したくありません。


調査後、このリンクは良いスタートを切った:

このチュートリアル(C#で記述)は、vb.netを使用して実行しようとしているものと非常によく似ています。


誰かがこれに取り組む方法についてのポインタを提供できますか?本当にありがたいです。

13
Brock Gion

私の解決策:

私は2つのアプローチを試みました:

AutoItは、特定のアプリケーションに対してより信頼性が高いため、私が使用したものでした。

ただし、Windows UIも機能しました。ここに両方の​​ソリューションがあります。


Windows UIオートメーションを使用する場合の手順

  • Spy ++を使用してボタンのコントロールIDを識別する
  • UIAutomationClientおよびUIAutomationTypesへの参照を追加する
  • ルートAE要素としてaeDesktopを設定し、ボタンのクリックを呼び出す

WindowsUI References

Imports System.Windows.Automation
Imports System.Threading
Imports System.Diagnostics

Public Class Form1

    Private aeDesktop As AutomationElement
    Private aeCalculator As AutomationElement

    Private ae5Btn As AutomationElement
    Private aeAddBtn As AutomationElement
    Private aeEqualsBtn As AutomationElement

    Private p As Process

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click

        Try

            'Set reference to the root ae element - the desktop
            aeDesktop = AutomationElement.RootElement

            'Launch Calculator application 
            p = Process.Start("C:\Windows\System32\calc.exe")

            '**********  Keep looping while waiting to get the reference to the "Calculator" on Desktop ************************************

            Dim numwaits As Integer = 0

            Do
                Debug.WriteLine("Looking for Calculator . . . ")
                aeCalculator = aeDesktop.FindFirst(TreeScope.Children, New PropertyCondition(AutomationElement.NameProperty, "Calculator"))
                numwaits += 1
                Thread.Sleep(100)

            Loop While aeCalculator Is Nothing AndAlso numwaits < 50

            If aeCalculator Is Nothing Then
                Throw New Exception("Failed to find Calculator")
            Else
                Debug.WriteLine("Found the Calculator Application!")
            End If

            '*********************************************************************************************************************************


            'NOTE: In spy++ Controlids are represented as hex (i.e. 00000087) - need to convert these to decimal (i.e. 135)

            '`5` btn
            '00000087 ---> 135
            Dim btn5hexID As String = "00000087"
            Dim btn5decimalID As String = Convert.ToInt32("00000087", 16).ToString

            '`+` btn
            '0000005D ---> 93
            Dim btnAddhexID As String = "0000005D"
            Dim btnAdddecimalID As String = Convert.ToInt32("0000005D", 16).ToString

            '`=` btn
            '00000079 ---> 121
            Dim btnEqualshexID As String = "00000079"
            Dim btnEqualsdecimalID As String = Convert.ToInt32("00000079", 16).ToString


            'Set reference for the `5` Button
            ae5Btn = aeCalculator.FindFirst(TreeScope.Descendants, New PropertyCondition(AutomationElement.AutomationIdProperty, btn5decimalID))

            'Set reference for the `+` Button
            aeAddBtn = aeCalculator.FindFirst(TreeScope.Descendants, New PropertyCondition(AutomationElement.AutomationIdProperty, btnAdddecimalID))

            'Set reference for the `=` Button
            aeEqualsBtn = aeCalculator.FindFirst(TreeScope.Descendants, New PropertyCondition(AutomationElement.AutomationIdProperty, btnEqualsdecimalID))


            'Manipulate calculator application by using invoke method to click on buttons
            Dim ipClick5Btn As InvokePattern = DirectCast(ae5Btn.GetCurrentPattern(InvokePattern.Pattern), InvokePattern)
            Dim ipClickAddBtn As InvokePattern = DirectCast(aeAddBtn.GetCurrentPattern(InvokePattern.Pattern), InvokePattern)
            Dim ipClickEqualsBtn As InvokePattern = DirectCast(aeEqualsBtn.GetCurrentPattern(InvokePattern.Pattern), InvokePattern)

            'Click 5
            ipClick5Btn.Invoke()

            'Click +
            ipClickAddBtn.Invoke()

            'Click 5
            ipClick5Btn.Invoke()

            'Click =
            ipClickEqualsBtn.Invoke()

            'Now calculator should display 10 as a result


            'Wait two seconds before closing
            Thread.Sleep(2000)

            'Exit Calculator
            p.CloseMainWindow()



        Catch ex As Exception

            'Handle any exceptions
            Debug.WriteLine("Fatal error: " & ex.Message)

        End Try

    End Sub

End Class



AutoItを使用する場合の手順

  • ボタンのClassnameNNを識別する
  • Calc.exeのハンドルを取得する
  • ボタンをクリックするには ControlClick 関数を使用します

Finder Tool


AutoItを使用している場合は、フルインストールを選択し、スクリプトエディターをダウンロードします。コードを貼り付けると、機能するはずです。


;Open up Calculator
Run('calc.exe')

;Pause execution until Calculator becomes active window
WinWaitActive('Calculator')

;Get the handle for Calculator
$hWnd = WinGetHandle('Calculator')

;Using the `Finder Tool`, you can drag and drop it onto controls to see all information (i.e. Text, Class, Handle, etc.)

;`ClassnameNN: Button10` is the number 5
;`ClassnameNN: Button23` is the addition operator (+)
;`ClassnameNN: Button28` is the equals operator (=)

;***** simple operation will perform 5 + 5 = 10 **************

;click 5
ControlClick($hWnd, "", "[CLASSNN:Button10]")

;click +
ControlClick($hWnd, "", "[CLASSNN:Button23]")

;click 5
ControlClick($hWnd, "", "[CLASSNN:Button10]")

;click =
ControlClick($hWnd, "", "[CLASSNN:Button28]")

;calculator should now display 10 as a result

;************************************************************

;Wait 2 seconds to show result
Sleep(2000)

;Close Calculator
WinClose($hWnd)

Exit


コメントですべての助けと提案をありがとう。それは途方もなく助けました。

17
Brock Gion