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

时间:2011-03-21 17:35:52

标签: c# .net vb.net forms reflection

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

我粗略地看一下在单独的AppDomain中加载应用程序,并通过反射执行Program.Main()以使应用程序运行。我也尝试从单独创建的Process对象中获取windowhandle(我学到的不会起作用)。

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

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

1 个答案:

答案 0 :(得分:4)

查看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

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

有很多关于这个主题的内容:

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