2011-03-21 39 views
1

我正在尝试自动化不提供此类自动化功能的产品。如何从单独的运行过程捕获表单事件

我已经粗略看了一下在单独的AppDomain中加载应用程序,并且还通过反射执行了Program.Main()以使应用程序运行。我也尝试从单独创建的Process对象获取窗口句柄(我学到的不会工作)。

如果我将其程序集引用添加到我的项目中,那么我可以引用“TheirProduct.FormMain”实例,如果有可能,是从该窗体捕获事件的最佳方法?

我需要做的是能够捕捉一对夫妇的事件,并对窗体执行一些Button.PerformClick()。

+0

这是不可能的,事件处理程序必须在进程中注册。看看Managed Spy ++。但与程序供应商或作者合作是取得成功的最佳途径。 – 2011-03-21 17:58:18

回答

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自动化库旨在与名为控件的模拟客户端一起工作,但它也适用于几乎任何程序。如果你没有很好地模拟你的程序,那么你将不得不像上面那样进行破解。

有大量关于这一主题阅读:

你可能会发现它很有用间谍++检查你的程序了。

+1

这绝对会让我受益匪浅。超级好消息,是供应商让我在他们的来源。 (这是意想不到的) – hometoast 2011-03-24 11:16:41