如何从单独的运行进程中捕获表单事件

hom*_*ast 1 .net c# vb.net forms reflection

我正在尝试自动化不提供此类自动化功能的产品。

我粗略地查看了在单独的 AppDomain 中加载应用程序,并通过反射执行 Program.Main() 来运行应用程序。我还尝试从单独创建的 Process 对象中获取窗口句柄(我了解到这是行不通的)。

如果我将他们的程序集的引用添加到我的项目中,以便我可以引用“TheirProduct.FormMain”的实例,如果可能的话,从该表单捕获事件的最佳方法是什么?

我需要做的是能够捕获几个事件,并对表单执行一些 Button.PerformClick()。

Chr*_*aas 5

查看 Microsoft UI 自动化库,它随 .Net 3.5 和 4.0 一起提供。这是4.0的代码示例,只需添加对UIAutomationClient和UIAutomationTypes的引用。该程序启动计算器并按下一些按钮。

Option Explicit On
Option Strict On

Imports System.Windows.Automation
Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ''//Start the calculator
        Using P = Process.Start("calc.exe")
            ''//Hack, pause for a bit while calculator starts
            System.Threading.Thread.Sleep(2000)

            ''//Try and grab the calculator window
            Dim CalcWindow = AutomationElement.FromHandle(P.MainWindowHandle)

            ''//Make sure we've got something
            If CalcWindow Is Nothing Then Throw New ApplicationException("Could find calculator window")

            ''//Grab all of the calculator buttons
            Dim Buttons = CalcWindow.FindAll(TreeScope.Descendants, New PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button))
            If (Buttons Is Nothing) OrElse (Buttons.Count = 0) Then Throw New ApplicationException("Could not find any buttons on the calculator")

            ''//Grab individual buttons by label
            Dim B5 = GetObjectByLabel(Buttons, "5")
            Dim BAdd = GetObjectByLabel(Buttons, "Add")
            Dim B7 = GetObjectByLabel(Buttons, "7")
            Dim BEquals = GetObjectByLabel(Buttons, "Equals")

            ''//Press the buttons
            DirectCast(B5.GetCurrentPattern(InvokePattern.Pattern), InvokePattern).Invoke()
            DirectCast(BAdd.GetCurrentPattern(InvokePattern.Pattern), InvokePattern).Invoke()
            DirectCast(B7.GetCurrentPattern(InvokePattern.Pattern), InvokePattern).Invoke()
            DirectCast(BEquals.GetCurrentPattern(InvokePattern.Pattern), InvokePattern).Invoke()
        End Using
    End Sub
    Private Shared Function GetObjectByLabel(ByVal objects As AutomationElementCollection, ByVal label As String) As AutomationElement
        ''//Sanity check
        If objects Is Nothing Then Throw New ArgumentNullException("objects")
        If label Is Nothing Then Throw New ArgumentNullException("label")

        ''//Loop through each looking by name
        For Each B As AutomationElement In objects
            If B.Current.Name = label Then Return B
        Next

        Return Nothing
    End Function
End Class
Run Code Online (Sandbox Code Playgroud)

UI 自动化库旨在与具有命名控件的模拟客户端一起使用,但它也适用于几乎任何程序。如果你没有很好地模拟你的程序,那么你将不得不像我上面那样修改。

有很多关于这个主题的阅读:

您可能会发现使用 Spy++ 检查您的程序也很有用。