~UI Automationで画面情報取得!その2~ UI Automation with PowerShell 奮戦記 10日目

UI Automation*1で遊ぼう!

UI Automation の画面情報の取得機能を使用したWindows設定書生成の自動化に挑戦しています。Windowsの標準実装のみ、PowerShellのみで動作させることを目指しています。

UI Automationでの画面操作の捕捉をPowerShellで出来るようにEventタイプを.Net Framworkで実装しました。
実装した開発ライブラリ、共通で使用するスクリプトについては以下を確認してくださいね。
https://amon52280sub.hateblo.jp/entry/2019/01/23/032420


画面情報を取得してみましょう。
ツリー構造で親子関係を見やすくしました。
PowerShell Version3(管理者権限)で実行してみる。

[CmdletBinding()]
Param (
  [int]$global:delay = 500
)

# UI Automation 共通ファンクションを組み込む
. .\UIA.ps1

# 初期化
$global:uia = UIA_Init

# Timer イベント捕捉
$global:timer = New-Object System.Timers.Timer
$timer.Interval = 100
$timer.Enabled = $false
Register-ObjectEvent -InputObject $timer -EventName Elapsed -Action {
  try {
  $name = $ev[0].current.name
  $controltype = $ev[0].current.localizedcontroltype
  $classname = $ev[0].current.classname
  $eventid = $ev[1].EventId.ProgrammaticName

  # ウインドウ or ダイアログ 
  $p = UIA_GetParentElement $ev[0]
  Write-Host $($p | Out-String)
  Write-Host ($p -ne $null)
  if ($p -ne $null) {
    # ツリー構造で表示
    Write-Host $(UIA_GetElementTreeWithNest $p | UIA_OutPut -mode ElementWithNest | Out-String)
  }
  Write-Host $(UIA_OutPut -element $ev[0] -event $ev[1] -mode Event | Out-String)
  Write-Host $($ev[0].GetSupportedPatterns() | Out-String)
  $timer.Enabled = $false
  } catch {
    Write-Host $_
  }
} | Out-Null

# UI Automation イベント捕捉
Register-ObjectEvent -InputObject $uia -EventName UIChange -Action {
  try {
  $timer.Enabled = $false

  $global:ev = $args
  $name = $ev[0].current.name
  $controltype = $ev[0].current.localizedcontroltype
  $classname = $ev[0].current.classname
  $eventid = $ev[1].EventId.ProgrammaticName

  if ($name -match "powershell") {return}
  switch ($eventid) {
    "AutomationElementIdentifiers.AutomationFocusChangedEvent" {
      $uia.SetEvent($ev[0])
      $timer.Interval = $delay
      $timer.Enabled = $true
    }
    "AutomationElementIdentifiers.AutomationPropertyChangedEvent" {
      $timer.Interval = $delay
      $timer.Enabled = $false
    }
    "WindowPatternIdentifiers.WindowOpenedProperty"{
      # ツリー構造で表示
      Write-Host $(UIA_GetElementTreeWithNest $ev[0] | UIA_OutPut -mode ElementWithNest | Out-String)
      Write-Host $(UIA_OutPut -element $ev[0] -event $ev[1] -mode Event | Out-String)
      $timer.Interval = $delay
      $timer.Enabled = $false
    }
    default {
      Write-Host $(UIA_OutPut -element $ev[0] -event $ev[1] -mode Event | Out-String)
      $timer.Interval = $delay
      $timer.Enabled = $false
    }
  }
  } catch {
    Write-Host $_
  }  
} | Out-Null

# イベントスタート
$uia.StartEvent()
"画面情報取得スタート!!"

実行結果

f:id:amon52280:20181203235901p:plainf:id:amon52280:20181203235718p:plain
システムのプロパティ画面を取得

UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest

ControlType  ClassName       Name
ダイアログ        #32770          システムのプロパティ
  ボタン        Button          OK
  ボタン        Button          キャンセル
  ボタン        Button          適用(A)
  タブ         SysTabControl32
    タブ項目                     コンピューター名
    タブ項目                     ハードウェア
    タブ項目                     詳細設定
      テキスト   Static          Administrator としてログオンしない場合は、これらのほとんどは変更できません。
      グループ   Button          パフォーマンス
      テキスト   Static          視覚効果、プロセッサのスケジュール、メモリ使用、および仮想メモリ
      ボタン    Button          設定(S)...
      グループ   Button          ユーザー プロファイル
      テキスト   Static          サインインに関連したデスクトップ設定
      ボタン    Button          設定(E)...
      グループ   Button          起動と回復
      テキスト   Static          システム起動、システム障害、およびデバッグ情報
      ボタン    Button          設定(T)
      ボタン    Button          環境変数(N)...
    タブ項目                     システムの保護
    タブ項目                     リモート
  タイトル バー                    システムのプロパティ
    メニュー バー                  システム メニュー バー
      メニュー項目                 システム
    ボタン                      閉じる




ControlType ClassName EventID                                       Name
ダイアログ       #32770    WindowPatternIdentifiers.WindowOpenedProperty システムのプロパティ



PS D:\開発\10DAY> UIA_GetParentElement

LocalizedControlType ClassName Name
タブ項目                           コンピューター名



UIA_GetParentElement

LocalizedControlType ClassName       Name
タブ                   SysTabControl32



UIA_GetParentElement

LocalizedControlType ClassName Name
ダイアログ                #32770    システムのプロパティ




Cached                                                                   Current
System.Windows.Automation.AutomationElement+AutomationElementInformation System.Windows.Automation.AutomationElement...



True
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest
UIA_GetElementTreeWithNest

ControlType  ClassName       Name
ダイアログ        #32770          システムのプロパティ
  ボタン        Button          OK
  ボタン        Button          キャンセル
  ボタン        Button          適用(A)
  タブ         SysTabControl32
    タブ項目                     コンピューター名
      テキスト   Static          コンピューターの説明(D):
      編集     Edit            コンピューターの説明(D):
      テキスト   Static          例: "キッチンのコンピューター"、"仕事用コンピューター"
      テキスト   Static          フル コンピューター名:
      編集     Edit            フル コンピューター名:
      テキスト   Static          ワークグループ:
      編集     Edit            ワークグループ:
      テキスト   Static          ドメインまたはワークグループに参加するためのウィザードを使用するには [ネットワーク ID] をク
リックしてください。
      ボタン    Button          ネットワーク ID(N)...
      テキスト   Static          このコンピューターの名前を変更するには、[変更] をクリックしてください。

      ボタン    Button          変更(C)...
      テキスト   Static
      イメージ   Static
      テキスト   Static          次の情報は、このコンピューターをネットワーク上で識別するために使われます。

    タブ項目                     ハードウェア
    タブ項目                     詳細設定
    タブ項目                     システムの保護
    タブ項目                     リモート
  タイトル バー                    システムのプロパティ
    メニュー バー                  システム メニュー バー
      メニュー項目                 システム
    ボタン                      閉じる




ControlType ClassName EventID                                                  Name
編集          Edit      AutomationElementIdentifiers.AutomationFocusChangedEvent コンピューターの説明(D):




   Id ProgrammaticName
10002 ValuePatternIdentifiers.Pattern
10014 TextPatternIdentifiers.Pattern

共通ファンクション(UIA.ps1)のUIA_GetElementTreeWithNestで子エレメントを再帰呼び出しで検索してツリー構造を構築しています。

見やすくなりました。 設定書の構成がイメージ出来ますね。

*1:ここでのUI AutomationはSystem.Windows.Automationのことです