2

请耐心等待,我是一名尝试 WinForms 应用程序的 Web 开发人员。

回复时请不要评论我的应用程序的目的是否是“最佳实践”等......这是我需要编写的应用程序,无论好坏,我不能浪费时间解释“为什么” . 我要求您就(1)我正在尝试做的事情是否可能(2)完成我正在尝试做的事情的“最佳”方式提供建议。

所以,这就是我正在尝试做的事情:我需要编写一个 WinForms 应用程序,该应用程序将从供应商应用程序读取数据,向最终用户显示某些记录并允许他们选择将记录“传输”到另一个供应商应用程序。挂断……目标系统不公开任何 api,没有存储过程,没有提供用于插入数据的“好”方法,除了将其输入到他们的 GUI 中。(相信我,一个由 3 人组成的团队调查了实现自动化的所有可能性)

所以这个 WinForms 应用程序将利用 Microsoft.VisualBasic.Interaction.AppActivate(string) 并将数据直接插入到目标系统输入窗口的字段中。目标系统在某些字段上具有 F1 帮助,因此如果您将焦点放在该字段上并按“F1”,或者,如果您在其中一个字段中输入无效数据,则会弹出一个名为“帮助”的子窗口以提供指导.

因此,我的应用程序正在插入,使用 SendKeys.SendWait(string) 将数据写入此应用程序的字段,然后遇到一些无效数据并弹出帮助窗口,我的应用程序继续写出其余数据,但现在它都被写入帮助窗口中的 1 字段,因为该窗口现在具有焦点。

百万美元的问题...

有没有办法从我的 WinForms 应用程序中检测到帮助窗口已在目标系统中激活,以便我可以解决它?


更新

第一次尝试这个应用程序时,我使用了 UIAutomationClient 库。我无法成功激活目标窗口并写入第一个字段。经过一天的战斗,我不得不开始寻找替代品。

4

1 回答 1

2

我有一些工作代码的开始。我想我有足够的东西,这可能对其他人有用。

我找到了一种使用 UIAutomation 库而不是 Microsoft.VisualBasic 库的方法。有很多试验和错误,但这比我使用 VisualBasic 库的前几次尝试要“灵活”得多。

我使用 StructureChanged 事件来检测在此概念验证应用程序的先前迭代中弹出的帮助窗口。我能够成功检测到“帮助”窗口弹出,但我在尝试处理“帮助”窗口的外观时遇到了障碍。我的应用程序中仍然有事件处理程序,但由于某种原因现在没有弹出帮助窗口,我尝试将无效数据强制输入其中一个字段以测试帮助窗口的处理,但没有出现帮助窗口。这对我来说不是问题,因为帮助窗口给我带来了麻烦,但我觉得有必要提及它,因为这篇文章是在询问我如何检测帮助窗口的外观。

我使用的一些资源:

http://msdn.microsoft.com/en-us/library/ms747327%28v=vs.110%29.aspx

https://www.universalthread.com/ViewPageArticle.aspx?ID=199

http://msdn.microsoft.com/en-us/library/ms750582%28v=vs.110%29.aspx

http://msdn.microsoft.com/en-us/library/windows/desktop/dd318521%28v=vs.85%29.aspx

private void IncidentGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
  if ((e.RowIndex < 0) || (e.ColumnIndex < 0))
    return;

  // Grab the data object that populated the row
  Incident incident = (Incident)IncidentGridView.Rows[e.RowIndex].DataBoundItem;

  // Create a property condition with the element's type
  PropertyCondition typeCondition = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window);
  // Create a property condition with the element's name
  PropertyCondition nameCondition = new PropertyCondition(AutomationElement.NameProperty, "Incident");
  // Create the conjunction condition
  AndCondition andCondition = new AndCondition(typeCondition, nameCondition);
  // Ask the Desktop to find the element within its children with the given condition
  _mainWindow = AutomationElement.RootElement.FindFirst(TreeScope.Children, andCondition);

  #region Register Automation Events
  //AutomationEventHandler handler = new AutomationEventHandler(OnWindowOpened);
  //Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, _mainWindow, TreeScope.Element, handler);
  Automation.AddStructureChangedEventHandler(_mainWindow, TreeScope.Children, new StructureChangedEventHandler(OnStructureChanged));
  #endregion

  // Wait for the application
  Thread.Sleep(2000);

  // Write the incident to the Incident window
  PropertyCondition idCondition = new PropertyCondition(AutomationElement.AutomationIdProperty, "3279");
  AutomationElement reportedDate = _mainWindow.FindFirst(TreeScope.Descendants, idCondition);
  InsertTextUsingUIAutomation(reportedDate, incident.ReportedDate);

  PropertyCondition idCondition2 = new PropertyCondition(AutomationElement.AutomationIdProperty, "4256");
  AutomationElement reportedTime = _mainWindow.FindFirst(TreeScope.Descendants, idCondition2);
  InsertTextUsingUIAutomation(reportedTime, incident.ReportedTime);

  PropertyCondition idCondition4 = new PropertyCondition(AutomationElement.AutomationIdProperty, "7256");
  AutomationElement status = _mainWindow.FindFirst(TreeScope.Descendants, idCondition4);
  InsertTextUsingUIAutomation(status, "WAR");

  PropertyCondition idCondition5 = new PropertyCondition(AutomationElement.AutomationIdProperty, "5404");
  AutomationElement natureOfCall = _mainWindow.FindFirst(TreeScope.Descendants, idCondition5);
  InsertTextUsingUIAutomation(natureOfCall, "TRAF WARN");

  PropertyCondition idCondition11 = new PropertyCondition(AutomationElement.AutomationIdProperty, "4935");
  AutomationElement location = _mainWindow.FindFirst(TreeScope.Descendants, idCondition11);
  InsertTextUsingUIAutomation(location, incident.Location);

  PropertyCondition idCondition12 = new PropertyCondition(AutomationElement.AutomationIdProperty, "2876");
  AutomationElement city = _mainWindow.FindFirst(TreeScope.Descendants, idCondition12);
  InsertTextUsingUIAutomation(city, incident.City);

  PropertyCondition idCondition15 = new PropertyCondition(AutomationElement.AutomationIdProperty, "5693");
  AutomationElement officer = _mainWindow.FindFirst(TreeScope.Descendants, idCondition15);
  InsertTextUsingUIAutomation(officer, incident.Officer);

  PropertyCondition idCondition19 = new PropertyCondition(AutomationElement.AutomationIdProperty, "4023");
  AutomationElement fromDate = _mainWindow.FindFirst(TreeScope.Descendants, idCondition19);
  InsertTextUsingUIAutomation(fromDate, incident.FromDate);

  PropertyCondition idCondition20 = new PropertyCondition(AutomationElement.AutomationIdProperty, "4042");
  AutomationElement fromTime = _mainWindow.FindFirst(TreeScope.Descendants, idCondition20);
  InsertTextUsingUIAutomation(fromTime, incident.FromTime);

  PropertyCondition idCondition21 = new PropertyCondition(AutomationElement.AutomationIdProperty, "7556");
  AutomationElement toDate = _mainWindow.FindFirst(TreeScope.Descendants, idCondition21);
  InsertTextUsingUIAutomation(toDate, incident.ToDate);

  PropertyCondition idCondition22 = new PropertyCondition(AutomationElement.AutomationIdProperty, "7576");
  AutomationElement toTime = _mainWindow.FindFirst(TreeScope.Descendants, idCondition22);
  InsertTextUsingUIAutomation(toTime, incident.ToTime);

  PropertyCondition idCondition30 = new PropertyCondition(AutomationElement.AutomationIdProperty, "2001");
  AutomationElement remarks = _mainWindow.FindFirst(TreeScope.Descendants, idCondition30);
  InsertTextUsingUIAutomation(remarks, incident.Remarks);


  MessageBox.Show("Incident was transferred.");
}

这是 StructureChangedEvent 的事件处理程序:

 private void OnStructureChanged(object sender, StructureChangedEventArgs e)
{
  AutomationElement element = sender as AutomationElement;

  if (e.StructureChangeType == StructureChangeType.ChildAdded)
  {
    Object windowPattern;
    if (false == element.TryGetCurrentPattern(WindowPattern.Pattern, out windowPattern))
      return;

    if (element.Current.Name == "Help")
    {
      // How do we want to handle this???
      MessageBox.Show("Waiting 30 seconds to allow user to resolve data issue.");
      Thread.Sleep(30000);
    }
  }
}
于 2014-09-19T15:27:09.217 回答