在 .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;
    }


}