This is a UI Automation method that can detect a Window Opened event anywhere in the System, identify the Window using the Text of one its child elements and close the Window upon positive identification.
The detection is initialized using Automation.AddAutomationEventHandler with WindowPattern.WindowOpenedEvent and Automation Element argument set to AutomationElement.RootElement, which, having no other ancestors, identifies the whole Desktop (any Window).
The WindowWatcher
class exposes a public method (WatchWindowBySubElementText
) that allows to specify the Text contained in one of the sub elements of a Window that just opened. If the specified Text is found, the method closes the Window and notifies the operation using a custom event handler that a subscriber can use to determine that the watched Window has been detected and closed.
Sample usage, using the Text string as provided in the question:
WindowWatcher watcher = new WindowWatcher();
watcher.ElementFound += (obj, evt) => { MessageBox.Show("Found and Closed!"); };
watcher.WatchWindowBySubElementText("Original message");
WindowWatcher
class:
This class requires a Project Reference to these assemblies:
UIAutomationClient
UIAutomationTypes
Note that, upon identification, the class event removes the Automation
event handler before notifying the subscribers. This is just an
example: it points out that the handlers need to be removed at some
point. The class could implement IDisposable
and remove the
handler(s) when disposed of.
EDIT:
Changed the condition that doesn't consider a Window created in the current Process:
if (element is null || element.Current.ProcessId != Process.GetCurrentProcess().Id)
As noted in the comments, it imposes a limitation that is probably not necessary: the Dialog could also belong to the current Process. I left there just the null
check.
using System.Diagnostics;
using System.Windows.Automation;
public class WindowWatcher
{
public delegate void ElementFoundEventHandler(object sender, EventArgs e);
public event ElementFoundEventHandler ElementFound;
public WindowWatcher() { }
public void WatchWindowBySubElementText(string ElementText) =>
Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent,
AutomationElement.RootElement, TreeScope.Subtree, (UIElm, evt) => {
AutomationElement element = UIElm as AutomationElement;
try {
if (element is null) return;
AutomationElement childElm = element.FindFirst(TreeScope.Children,
new PropertyCondition(AutomationElement.NameProperty, ElementText));
if (childElm != null) {
(element.GetCurrentPattern(WindowPattern.Pattern) as WindowPattern).Close();
OnElementFound(new EventArgs());
}
}
catch (ElementNotAvailableException) {
// Ignore: generated when a Window is closed. Its AutomationElement
// is no longer available. Usually a modal dialog in the current process.
}
});
public void OnElementFound(EventArgs e)
{
// Automation.RemoveAllEventHandlers(); <= If single use. Add to IDisposable.Dispose()
ElementFound?.Invoke(this, e);
}
}