我想使用C#中的Microsoft UIAutomation.

我收集了我在互联网上找到的一些信息,最后得到了以下代码(使用Nuget包"Interop.UIAutomationClient"Version="10.19041.0").

using System;
using UIA = Interop.UIAutomationClient;

namespace TestUIA
{
    internal class Program
    {
         static void Main(string[] args)
        {
            Console.WriteLine("Starting...");
            UIA.IUIAutomation NativeAutomation = new UIA.CUIAutomation8();
            var Desktop = NativeAutomation.GetRootElement();
            Console.WriteLine("Destop name is {0}", Desktop.CurrentName);
            Console.WriteLine("Ending...");
        }
    }
}

很好用! 在我的Windows 11 22 H2上的实际结果是

现在我想列举桌面 children .我知道我必须使用FindAll方法. 不幸的是,我只能编码第一个参数,如

    Desktop.FindAll( UIA.TreeScope.TreeScope_Children,

但我不知道如何编码第二个论点...如果我是在C++上,我会用IUIAutomation::CreateTrueCondition...

QUESTION:如何使用Nuget包"Interop.UIAutomationClient"在C#中将"True Condition"传递给FindAll

推荐答案

您不需要任何Nuget,只需将Windows中的UIAutomationClient COM DLL作为COM对象引用即可:

enter image description here

现在,要创建真实的条件,如您所说,您必须使用在...上实现的IUIAutomation::CreateTrueCondition method.CUIAutomation8(根类,它实现了IUIAutomation).我已经编写了一些扩展方法来简化这一过程:

using System;
using System.Collections.Generic;
using System.Linq;
using UIAutomationClient;

internal class Program
{
    static void Main()
    {
        Console.WriteLine("Starting...");
        var desktop = UIAUtilities.Automation.GetRootElement();

        Console.WriteLine("Destop name is {0}", desktop.CurrentName);
        foreach (var element in desktop.EnumerateAll(TreeScope.TreeScope_Children))
        {
            Console.WriteLine(element.CurrentName);
        }
        Console.WriteLine("Ending...");
    }
}

public static class UIAUtilities
{
    private static readonly Lazy<CUIAutomation8> _automation = new(() => new CUIAutomation8());
    public static CUIAutomation8 Automation => _automation.Value;

    public static IEnumerable<IUIAutomationElement> EnumerateAll(this IUIAutomationElement element, TreeScope scope = TreeScope.TreeScope_Children, IUIAutomationCondition condition = null)
    {
        if (element == null)
            return Enumerable.Empty<IUIAutomationElement>();

        condition ??= Automation.CreateTrueCondition();
        return ForEach(element.FindAll(scope, condition));
    }

    public static IEnumerable<IUIAutomationElement> ForEach(this IUIAutomationElementArray array)
    {
        if (array == null)
            yield break;

        for (var i = 0; i < array.Length; i++)
        {
            var element = array.GetElement(i);
            if (element != null)
                yield return element;
        }
    }
}

下面是带有COM引用的项目文件(.NET core+)应该是什么样子:

<Project Sdk="Microsoft.NET.Sdk">
  ...
    <ItemGroup>
      <COMReference Include="UIAutomationClient">
        <WrapperTool>tlbimp</WrapperTool>
        <VersionMinor>0</VersionMinor>
        <VersionMajor>1</VersionMajor>
        <Guid>944de083-8fb8-45cf-bcb7-c477acb2f897</Guid>
        <Lcid>0</Lcid>
        <Isolated>false</Isolated>
        <EmbedInteropTypes>true</EmbedInteropTypes>
      </COMReference>
    </ItemGroup>
  ...
</Project>

Csharp相关问答推荐

如何使用FastEndpoints和.NET 8 WebAppliationBuilder进行集成测试?

在C# 11之前, struct 中的每个字段都必须显式分配?不能繁殖

为什么使用DXGI输出复制和Direct 3D时捕获的图像数据全为零?

FromServices不使用WebAppliationFactory程序>

如何在Visual Studio中为C# spread操作符设置格式规则?

使用命令初始化可绑定属性

使用可信第三方的Iext8.Net pdf签名

使用泛型可空类实现接口

System.Text.Json .NET 8多形态语法化

在IAsyncEnumerable上先调用,然后跳过(1)可以吗?

HelperText属性不支持复杂内容(混合C#和标记)

用C#从XML内部元素中获取特定值

.NET Google Workspace API获取错误CS0266

如何在C#中从MongoDB IPipelineStageDefinition中获取聚合命令的字段/选项?

在.NET Maui中,Flyoutindow/Hamburger菜单可以在shell 之外实现吗?

如何在.NET Core 8中自定义标识用户模型

在ObservableCollection上使用[NotifyPropertyChangedFor()]源代码生成器不会更新UI

在C#和HttpClient中使用REST API

.NET EF Core Automapper项目到筛选不起作用

实例化列表时的集合表达式是什么?