在 .NET 中关闭另一个应用程序的 window
Close a window of another application in .NET
我想关闭一个 window 的外部应用程序,但只关闭一个 window,而不是整个应用程序。例如,我有以下应用程序 (Resource-Manager),其中有两个打开 windows:
我想关闭 window "Generate vb-code",但让 "Resource-Manager" 打开应用程序 运行。
在 .NET 中有什么方法可以做到这一点吗?
如果您想从另一个 .Net 应用程序关闭 'Generate vb-code' window。您应该可以通过 UIAutomation.
实现此目的
使用此框架,您可以访问应用程序并获取打开的句柄 windows 并关闭它们。
这个link解释了寻找UI元素的路径。
编辑添加的代码示例
class Program
{
static void Main(string[] args)
{
AutomationElement mainWindow = AutomationElement.RootElement;
var winCollection = mainWindow.FindAll(TreeScope.Children, Condition.TrueCondition);
foreach (AutomationElement element in winCollection)
{
if (element.Current.Name == "Generate vb-code")
{
var closeButton = element.FindDescendentByIdPath(new[] { "TitleBar", "Close" });
if (closeButton != null)
closeButton.GetInvokePattern().Invoke();
}
}
}
}
public static class AutomationExtensions
{
public static void EnsureElementIsScrolledIntoView(this AutomationElement element)
{
if (!element.Current.IsOffscreen)
{
return;
}
if (!(bool)element.GetCurrentPropertyValue(AutomationElement.IsScrollItemPatternAvailableProperty))
{
return;
}
var scrollItemPattern = element.GetScrollItemPattern();
scrollItemPattern.ScrollIntoView();
}
public static AutomationElement FindDescendentByConditionPath(this AutomationElement element, IEnumerable<Condition> conditionPath)
{
if (!conditionPath.Any())
{
return element;
}
var result = conditionPath.Aggregate(
element,
(parentElement, nextCondition) => parentElement == null
? null
: parentElement.FindChildByCondition(nextCondition));
return result;
}
public static AutomationElement FindDescendentByIdPath(this AutomationElement element, IEnumerable<string> idPath)
{
var conditionPath = CreateConditionPathForPropertyValues(AutomationElement.AutomationIdProperty, idPath.Cast<object>());
return FindDescendentByConditionPath(element, conditionPath);
}
public static AutomationElement FindDescendentByNamePath(this AutomationElement element, IEnumerable<string> namePath)
{
var conditionPath = CreateConditionPathForPropertyValues(AutomationElement.NameProperty, namePath.Cast<object>());
return FindDescendentByConditionPath(element, conditionPath);
}
public static IEnumerable<Condition> CreateConditionPathForPropertyValues(AutomationProperty property, IEnumerable<object> values)
{
var conditions = values.Select(value => new PropertyCondition(property, value));
return conditions.Cast<Condition>();
}
/// <summary>
/// Finds the first child of the element that has a descendant matching the condition path.
/// </summary>
/// <param name="element">The element.</param>
/// <param name="conditionPath">The condition path.</param>
/// <returns></returns>
public static AutomationElement FindFirstChildHavingDescendantWhere(this AutomationElement element, IEnumerable<Condition> conditionPath)
{
return
element.FindFirstChildHavingDescendantWhere(
child => child.FindDescendentByConditionPath(conditionPath) != null);
}
/// <summary>
/// Finds the first child of the element that has a descendant matching the condition path.
/// </summary>
/// <param name="element">The element.</param>
/// <param name="conditionPath">The condition path.</param>
/// <returns></returns>
public static AutomationElement FindFirstChildHavingDescendantWhere(this AutomationElement element, Func<AutomationElement, bool> condition)
{
var children = element.FindAll(TreeScope.Children, Condition.TrueCondition);
foreach (AutomationElement child in children)
{
if (condition(child))
{
return child;
}
}
return null;
}
public static AutomationElement FindChildById(this AutomationElement element, string automationId)
{
var result = element.FindChildByCondition(
new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
return result;
}
public static AutomationElement FindChildByName(this AutomationElement element, string name)
{
var result = element.FindChildByCondition(
new PropertyCondition(AutomationElement.NameProperty, name));
return result;
}
public static AutomationElement FindChildByClass(this AutomationElement element, string className)
{
var result = element.FindChildByCondition(
new PropertyCondition(AutomationElement.ClassNameProperty, className));
return result;
}
public static AutomationElement FindChildByProcessId(this AutomationElement element, int processId)
{
var result = element.FindChildByCondition(
new PropertyCondition(AutomationElement.ProcessIdProperty, processId));
return result;
}
public static AutomationElement FindChildByControlType(this AutomationElement element, ControlType controlType)
{
var result = element.FindChildByCondition(
new PropertyCondition(AutomationElement.ControlTypeProperty, controlType));
return result;
}
public static AutomationElement FindChildByCondition(this AutomationElement element, Condition condition)
{
var result = element.FindFirst(
TreeScope.Children,
condition);
return result;
}
/// <summary>
/// Finds the child text block of an element.
/// </summary>
/// <param name="element">The element.</param>
/// <returns></returns>
public static AutomationElement FindChildTextBlock(this AutomationElement element)
{
var child = TreeWalker.RawViewWalker.GetFirstChild(element);
if (child != null && child.Current.ControlType == ControlType.Text)
{
return child;
}
return null;
}
}
public static class PatternExtensions
{
public static string GetValue(this AutomationElement element)
{
var pattern = element.GetPattern<ValuePattern>(ValuePattern.Pattern);
return pattern.Current.Value;
}
public static void SetValue(this AutomationElement element, string value)
{
var pattern = element.GetPattern<ValuePattern>(ValuePattern.Pattern);
pattern.SetValue(value);
}
public static ScrollItemPattern GetScrollItemPattern(this AutomationElement element)
{
return element.GetPattern<ScrollItemPattern>(ScrollItemPattern.Pattern);
}
public static InvokePattern GetInvokePattern(this AutomationElement element)
{
return element.GetPattern<InvokePattern>(InvokePattern.Pattern);
}
public static SelectionItemPattern GetSelectionItemPattern(this AutomationElement element)
{
return element.GetPattern<SelectionItemPattern>(SelectionItemPattern.Pattern);
}
public static SelectionPattern GetSelectionPattern(this AutomationElement element)
{
return element.GetPattern<SelectionPattern>(SelectionPattern.Pattern);
}
public static TogglePattern GetTogglePattern(this AutomationElement element)
{
return element.GetPattern<TogglePattern>(TogglePattern.Pattern);
}
public static WindowPattern GetWindowPattern(this AutomationElement element)
{
return element.GetPattern<WindowPattern>(WindowPattern.Pattern);
}
public static T GetPattern<T>(this AutomationElement element, AutomationPattern pattern) where T : class
{
var patternObject = element.GetCurrentPattern(pattern);
return patternObject as T;
}
}
我想关闭一个 window 的外部应用程序,但只关闭一个 window,而不是整个应用程序。例如,我有以下应用程序 (Resource-Manager),其中有两个打开 windows:
我想关闭 window "Generate vb-code",但让 "Resource-Manager" 打开应用程序 运行。
在 .NET 中有什么方法可以做到这一点吗?
如果您想从另一个 .Net 应用程序关闭 'Generate vb-code' window。您应该可以通过 UIAutomation.
实现此目的使用此框架,您可以访问应用程序并获取打开的句柄 windows 并关闭它们。
这个link解释了寻找UI元素的路径。
编辑添加的代码示例
class Program
{
static void Main(string[] args)
{
AutomationElement mainWindow = AutomationElement.RootElement;
var winCollection = mainWindow.FindAll(TreeScope.Children, Condition.TrueCondition);
foreach (AutomationElement element in winCollection)
{
if (element.Current.Name == "Generate vb-code")
{
var closeButton = element.FindDescendentByIdPath(new[] { "TitleBar", "Close" });
if (closeButton != null)
closeButton.GetInvokePattern().Invoke();
}
}
}
}
public static class AutomationExtensions
{
public static void EnsureElementIsScrolledIntoView(this AutomationElement element)
{
if (!element.Current.IsOffscreen)
{
return;
}
if (!(bool)element.GetCurrentPropertyValue(AutomationElement.IsScrollItemPatternAvailableProperty))
{
return;
}
var scrollItemPattern = element.GetScrollItemPattern();
scrollItemPattern.ScrollIntoView();
}
public static AutomationElement FindDescendentByConditionPath(this AutomationElement element, IEnumerable<Condition> conditionPath)
{
if (!conditionPath.Any())
{
return element;
}
var result = conditionPath.Aggregate(
element,
(parentElement, nextCondition) => parentElement == null
? null
: parentElement.FindChildByCondition(nextCondition));
return result;
}
public static AutomationElement FindDescendentByIdPath(this AutomationElement element, IEnumerable<string> idPath)
{
var conditionPath = CreateConditionPathForPropertyValues(AutomationElement.AutomationIdProperty, idPath.Cast<object>());
return FindDescendentByConditionPath(element, conditionPath);
}
public static AutomationElement FindDescendentByNamePath(this AutomationElement element, IEnumerable<string> namePath)
{
var conditionPath = CreateConditionPathForPropertyValues(AutomationElement.NameProperty, namePath.Cast<object>());
return FindDescendentByConditionPath(element, conditionPath);
}
public static IEnumerable<Condition> CreateConditionPathForPropertyValues(AutomationProperty property, IEnumerable<object> values)
{
var conditions = values.Select(value => new PropertyCondition(property, value));
return conditions.Cast<Condition>();
}
/// <summary>
/// Finds the first child of the element that has a descendant matching the condition path.
/// </summary>
/// <param name="element">The element.</param>
/// <param name="conditionPath">The condition path.</param>
/// <returns></returns>
public static AutomationElement FindFirstChildHavingDescendantWhere(this AutomationElement element, IEnumerable<Condition> conditionPath)
{
return
element.FindFirstChildHavingDescendantWhere(
child => child.FindDescendentByConditionPath(conditionPath) != null);
}
/// <summary>
/// Finds the first child of the element that has a descendant matching the condition path.
/// </summary>
/// <param name="element">The element.</param>
/// <param name="conditionPath">The condition path.</param>
/// <returns></returns>
public static AutomationElement FindFirstChildHavingDescendantWhere(this AutomationElement element, Func<AutomationElement, bool> condition)
{
var children = element.FindAll(TreeScope.Children, Condition.TrueCondition);
foreach (AutomationElement child in children)
{
if (condition(child))
{
return child;
}
}
return null;
}
public static AutomationElement FindChildById(this AutomationElement element, string automationId)
{
var result = element.FindChildByCondition(
new PropertyCondition(AutomationElement.AutomationIdProperty, automationId));
return result;
}
public static AutomationElement FindChildByName(this AutomationElement element, string name)
{
var result = element.FindChildByCondition(
new PropertyCondition(AutomationElement.NameProperty, name));
return result;
}
public static AutomationElement FindChildByClass(this AutomationElement element, string className)
{
var result = element.FindChildByCondition(
new PropertyCondition(AutomationElement.ClassNameProperty, className));
return result;
}
public static AutomationElement FindChildByProcessId(this AutomationElement element, int processId)
{
var result = element.FindChildByCondition(
new PropertyCondition(AutomationElement.ProcessIdProperty, processId));
return result;
}
public static AutomationElement FindChildByControlType(this AutomationElement element, ControlType controlType)
{
var result = element.FindChildByCondition(
new PropertyCondition(AutomationElement.ControlTypeProperty, controlType));
return result;
}
public static AutomationElement FindChildByCondition(this AutomationElement element, Condition condition)
{
var result = element.FindFirst(
TreeScope.Children,
condition);
return result;
}
/// <summary>
/// Finds the child text block of an element.
/// </summary>
/// <param name="element">The element.</param>
/// <returns></returns>
public static AutomationElement FindChildTextBlock(this AutomationElement element)
{
var child = TreeWalker.RawViewWalker.GetFirstChild(element);
if (child != null && child.Current.ControlType == ControlType.Text)
{
return child;
}
return null;
}
}
public static class PatternExtensions
{
public static string GetValue(this AutomationElement element)
{
var pattern = element.GetPattern<ValuePattern>(ValuePattern.Pattern);
return pattern.Current.Value;
}
public static void SetValue(this AutomationElement element, string value)
{
var pattern = element.GetPattern<ValuePattern>(ValuePattern.Pattern);
pattern.SetValue(value);
}
public static ScrollItemPattern GetScrollItemPattern(this AutomationElement element)
{
return element.GetPattern<ScrollItemPattern>(ScrollItemPattern.Pattern);
}
public static InvokePattern GetInvokePattern(this AutomationElement element)
{
return element.GetPattern<InvokePattern>(InvokePattern.Pattern);
}
public static SelectionItemPattern GetSelectionItemPattern(this AutomationElement element)
{
return element.GetPattern<SelectionItemPattern>(SelectionItemPattern.Pattern);
}
public static SelectionPattern GetSelectionPattern(this AutomationElement element)
{
return element.GetPattern<SelectionPattern>(SelectionPattern.Pattern);
}
public static TogglePattern GetTogglePattern(this AutomationElement element)
{
return element.GetPattern<TogglePattern>(TogglePattern.Pattern);
}
public static WindowPattern GetWindowPattern(this AutomationElement element)
{
return element.GetPattern<WindowPattern>(WindowPattern.Pattern);
}
public static T GetPattern<T>(this AutomationElement element, AutomationPattern pattern) where T : class
{
var patternObject = element.GetCurrentPattern(pattern);
return patternObject as T;
}
}