2

私は WinForms アプリケーションを試みている Web 開発者です。

返信するときは、私のアプリケーションの目的が「ベスト プラクティス」であるかどうかなどについてコメントしないでください。良くも悪くも、これは私が書く必要のあるアプリケーションであり、「理由」を説明するために時間を無駄にすることはできません。 . (1)私がやろうとしていることは可能ですか(2)私がやろうとしていることを達成するための「最良の」方法は何ですか?

そこで、私がやろうとしていることは次のとおりです。ベンダー アプリケーションからデータを読み取り、特定のレコードをエンド ユーザーに表示し、エンド ユーザーがレコードを別のベンダー アプリケーションに「転送」することを選択できるようにする WinForms アプリケーションを作成する必要があります。ハングアップ...宛先システムはAPIもsprocも公開せず、GUIに入力する以外に、データを挿入するための「適切な」方法を提供しません。(これについては私を信じてください。3 人のチームがこれを自動化する可能性をすべて調査しました)

したがって、この WinForms アプリは Microsoft.VisualBasic.Interaction.AppActivate(string) を利用し、宛先システムの入力ウィンドウのフィールドにデータを直接挿入します。宛先システムには特定のフィールドに関する F1 ヘルプがあるため、フィールドにフォーカスを移して「F1」を押すか、これらのフィールドのいずれかに無効なデータを入力すると、「ヘルプ」という名前の子ウィンドウがポップアップしてガイダンスが提供されます。 .

したがって、私のアプリはプラグインし、SendKeys.SendWait(string) を使用してこのアプリケーションのフィールドにデータを書き込みます。その後、無効なデータが検出され、ヘルプ ウィンドウがポップアップし、アプリは残りのデータを書き続けます。 、しかし今では、そのウィンドウにフォーカスがあるため、ヘルプ ウィンドウの 1 フィールドにすべてが書き込まれています。

百万ドルの質問...

WinForms アプリから、宛先システムでヘルプ ウィンドウがアクティブになっていることを検出して、それを回避する方法はありますか?


アップデート

このアプリケーションでの最初の試みは、UIAutomationClient ライブラリを使用しました。ターゲット ウィンドウをアクティブにして、最初のフィールドに書き込むことができませんでした。一日格闘した後、私は代替品を探し始めなければなりませんでした。

4

1 に答える 1

2

いくつかの作業コードの開始があります。これが他の誰かに役立つかもしれないのに十分だと思います。

Microsoft.VisualBasic ライブラリの代わりに UIAutomation ライブラリを使用する方法を見つけました。多くの試行錯誤がありましたが、これは、VisualBasic ライブラリを使用した最初の数回の試行よりもはるかに「スムーズ」です。

StructureChanged イベントを使用して、この概念実証アプリの前の繰り返しでポップアップするヘルプ ウィンドウを検出しました。ヘルプ ウィンドウがポップアップしたことは正常に検出できましたが、ヘルプ ウィンドウの外観を処理しようとして問題が発生していました。アプリケーションにはまだイベント ハンドラがありますが、何らかの理由でヘルプ ウィンドウが表示されなくなりました。無効なデータをフィールドの 1 つに強制的に入力して、ヘルプ ウィンドウの処理をテストしましたが、ヘルプ ウィンドウが表示されませんでした。ヘルプ ウィンドウが原因で問題が発生していたので、これは問題ではありませんが、この投稿でヘルプ ウィンドウの外観を検出する方法を尋ねていたので、言及する必要があると感じました。

私が使用したいくつかのリソース:

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 に答える