代码之家  ›  专栏  ›  技术社区  ›  anqooqie

如何使用PowerShell中的非托管UI自动化API

  •  2
  • anqooqie  · 技术社区  · 6 年前

    一个是托管DLL,它是 C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\UIAutomationClient.dll 另一个是非托管DLL,它是 C:\Windows\System32\UIAutomationCore.dll this post ,非托管API在可见元素的数量上优于托管API,因此我想使用非托管API。

    我试过三种方法,但都失败了。 你能告诉我正确的方法吗?

    方法#1:新对象-共对象

    $uia = New-Object -ComObject <ProgID of CUIAutomation>
    $root = $uia.GetRootElement()
    

    New-Object 需要ProgID,但 CUIAutomation 没有ProgID。

    ff48dba4-60ef-4201-aa87-54103eef594e ,那么,

    $type = [Type]::GetTypeFromCLSID("ff48dba4-60ef-4201-aa87-54103eef594e")
    $uia = [Activator]::CreateInstance($type)
    $root = $uia.GetRootElement()
    

    我还是不知道为什么。

    Method invocation failed because [System.__ComObject] does not contain a method named 'GetRootElement'.
    At line:1 char:1
    + $root = $uia.GetRootElement()
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
        + FullyQualifiedErrorId : MethodNotFound
    

    方法#3:添加类型

    Add-Type -Path "C:\Windows\System32\UIAutomationCore.dll"
    $uia = New-Object UIAutomationClient.CUIAutomation
    $root = $uia.GetRootElement()
    

    Add-Type 需要托管DLL。

    错误消息:

    Add-Type : Could not load file or assembly 'file:///C:\Windows\System32\UIAutomationCore.dll' or one of its dependencies. The module was expected to contain an assembly manifest. At line:1 char:1
    + Add-Type -Path "C:\Windows\System32\UIAutomationCore.dll"
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [Add-Type], BadImageFormatException
        + FullyQualifiedErrorId : System.BadImageFormatException,Microsoft.PowerShell.Commands.AddTypeCommand
    

    我尝试了另一种方法。(和失败)

    方法4:互操作DLL

    this post 说互操作DLL帮助了操作。 我安装了visualstudio并生成 Interop.UIAutomationClient.dll 按岗位程序办理。

    Add-Type -Path "Interop.UIAutomationClient.dll"
    $uia = New-Object UIAutomationClient.CUIAutomationClass
    $root = $uia.GetRootElement()
    $children = $root.FindAll([UIAutomationClient.TreeScope]::TreeScope_Children, $uia.CreateTrueCondition())
    

    我成功地获得了 $root ,但在 $children

    Method invocation failed because [System.__ComObject] does not contain a method named 'FindAll'.
    At line:1 char:1
    + $children = $root.FindAll([UIAutomationClient.TreeScope]::TreeScope_C ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
        + FullyQualifiedErrorId : MethodNotFound
    

    我还是不知道为什么。

    2 回复  |  直到 6 年前
        1
  •  0
  •   anqooqie    6 年前

    我还没有解决这个问题,但终于找到了另一个选择,那就是C#Interactive。 我将把这个问题留给PowerShell用户,但是,如果您可以使用C#Interactive作为PowerShell的替代方案,下面的部分可能会对您有所帮助。

    方法#5:C#交互式

    1. 生成 Interop.UIAutomationClient.dll this post .
    2. 在上运行以下脚本 csi.exe
    #r "Interop.UIAutomationClient.dll"
    var uia = new UIAutomationClient.CUIAutomation();
    var root = uia.GetRootElement();
    var children = root.FindAll(UIAutomationClient.TreeScope.TreeScope_Children, uia.CreateTrueCondition());
    

    仅供参考,如果同一文件夹中只存在以下文件,C#Interactive就可以工作(即,您可以在任何地方使用C#Interactive,只需从开发环境中带来以下文件即可)。

    • C:\Program Files (x86)\MSBuild\14.0\Bin\csi.exe
    • C:\Program Files (x86)\MSBuild\14.0\Bin\csi.rsp
    • C:\Program Files (x86)\MSBuild\14.0\Bin\Microsoft.CodeAnalysis.CSharp.dll
    • C:\Program Files (x86)\MSBuild\14.0\Bin\Microsoft.CodeAnalysis.CSharp.Scripting.dll
    • C:\Program Files (x86)\MSBuild\14.0\Bin\Microsoft.CodeAnalysis.dll
    • C:\Program Files (x86)\MSBuild\14.0\Bin\Microsoft.CodeAnalysis.Scripting.dll
    • C:\Program Files (x86)\MSBuild\14.0\Bin\System.AppContext.dll
    • C:\Program Files (x86)\MSBuild\14.0\Bin\System.Collections.Immutable.dll
    • C:\Program Files (x86)\MSBuild\14.0\Bin\System.Diagnostics.StackTrace.dll
    • C:\Program Files (x86)\MSBuild\14.0\Bin\System.IO.FileSystem.dll
    • C:\Program Files (x86)\MSBuild\14.0\Bin\System.Reflection.Metadata.dll
        2
  •  0
  •   junkew    6 年前

    方法2 你应该进入

    IID_IUIAutomation = "{30CBE57D-D9D0-452A-AB13-7AC5AC4825EE}"
    
    CLSID_UIAutomationClient = "{944DE083-8FB8-45CF-BCB7-C477ACB2F897}"
    ;CoClasses
    CLSID_CUIAutomation = "{FF48DBA4-60EF-4201-AA87-54103EEF594E}"
    

    评论

    下面的示例函数创建CUIAutomation对象并获取

    IUIAutomation *g_pAutomation; 
    
    BOOL InitializeUIAutomation() 
    { 
    CoInitialize(NULL); 
    HRESULT hr = CoCreateInstance(__uuidof(CUIAutomation), NULL, CLSCTX_INPROC_SERVER,  
        __uuidof(IUIAutomation), (void**)&g_pAutomation); 
    return (SUCCEEDED(hr)); 
    } 
    

    我无法让它在PS中工作,但也许这个答案有助于部分正确的方向(我有它在AutoIt中工作,但工作方式不同,你可以在谷歌上找到AutoIt IUIAutomation)

    $objCUI=[System.Runtime.InteropServices.Marshal]::GetTypeFromCLSID("30CBE57D-D9D0-452A-AB13-7AC5AC4825EE")
    

    $Type = [Type]::GetTypeFromCLSID('30CBE57D-D9D0-452A-AB13-7AC5AC4825EE')
    $objCUI = [System.Activator]::CreateInstance($Type)
    

    两个都跑,但当我

    $rootEl = $objCUI.GetType().InvokeMember(
    "GetRootElement", 
    "InvokeMethod", 
    $Null, 
    $objCUI, 
    @()
    )  
    

        3
  •  0
  •   Carsten    4 年前

    这个怎么样?:

    Add-Type -AssemblyName 'UIAutomationClient'
    $ae = [System.Windows.Automation.AutomationElement]
    $cTrue = [System.Windows.Automation.PropertyCondition]::TrueCondition
    $root = $ae::RootElement
    $winNames = $root.FindAll("Children", $cTrue).current.name