param([string]$Mode = "element") $ErrorActionPreference = "Continue" Add-Type -AssemblyName UIAutomationClient, UIAutomationTypes Add-Type -AssemblyName System.Windows.Forms Add-Type -MemberDefinition "[DllImport(`"user32.dll`")] public static extern short GetAsyncKeyState(int key); [DllImport(`"user32.dll`", CharSet = CharSet.Unicode)] public static extern int GetWindowTextW(IntPtr h, System.Text.StringBuilder sb, int max);" -Name PickW32 -Namespace RpaPick | Out-Null if ($Mode -eq "windows") { $wins = @() foreach ($p in Get-Process) { if ($p.MainWindowHandle -ne [IntPtr]::Zero -and $p.MainWindowTitle) { $wins += @{ title = $p.MainWindowTitle; process = $p.ProcessName } } } Write-Output (ConvertTo-Json $wins -Compress -AsArray) exit 0 } function Get-DeepestAtPoint([double]$px, [double]$py) { $point = New-Object System.Windows.Automation.Point($px, $py) $cur = [System.Windows.Automation.AutomationElement]::FromPoint($point) if (-not $cur) { return $null } for ($depth = 0; $depth -lt 30; $depth++) { $children = $cur.FindAll([System.Windows.Automation.TreeScope]::Children, [System.Windows.Automation.Condition]::TrueCondition) $next = $null $nextArea = [double]::MaxValue foreach ($c in $children) { try { $r = $c.Current.BoundingRectangle if ($r.Width -gt 0 -and $r.Height -gt 0 -and $px -ge $r.X -and $px -le ($r.X + $r.Width) -and $py -ge $r.Y -and $py -le ($r.Y + $r.Height)) { $area = $r.Width * $r.Height if ($area -lt $nextArea) { $next = $c; $nextArea = $area } } } catch {} } if (-not $next) { break } $cur = $next } return $cur } $form = New-Object System.Windows.Forms.Form $form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::None $form.TopMost = $true $form.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual $form.Location = New-Object System.Drawing.Point(20, 20) $form.Size = New-Object System.Drawing.Size(460, 130) $form.BackColor = [System.Drawing.Color]::FromArgb(20, 60, 120) $label = New-Object System.Windows.Forms.Label $label.Dock = [System.Windows.Forms.DockStyle]::Fill $label.ForeColor = [System.Drawing.Color]::White $label.Font = New-Object System.Drawing.Font("Microsoft YaHei", 11) $label.Text = "移动鼠标选择元素..." $form.Controls.Add($label) $form.Show() $prevDown = $false $result = $null while ($true) { $ptX = [System.Windows.Forms.Cursor]::Position.X $ptY = [System.Windows.Forms.Cursor]::Position.Y $el = Get-DeepestAtPoint $ptX $ptY $down = ([RpaPick.PickW32]::GetAsyncKeyState(32) -band 0x8000) -ne 0 $esc = ([RpaPick.PickW32]::GetAsyncKeyState(27) -band 0x8000) -ne 0 if ($esc) { break } if ($el) { $c = $el.Current $ctrlName = $c.ControlType.ProgrammaticName.Replace("ControlType.", "") $label.Text = "名称: " + $c.Name + [Environment]::NewLine + "类型: " + $ctrlName + [Environment]::NewLine + "空格=拾取 Esc=取消" } if ($down -and $el) { $c = $el.Current $rootName = "" $walker = [System.Windows.Automation.TreeWalker]::ControlViewWalker $anc = $walker.GetParent($el) while ($anc -and -not $anc.Equals([System.Windows.Automation.AutomationElement]::RootElement)) { $h = $anc.Current.NativeWindowHandle if ($h -ne 0) { $sb = New-Object System.Text.StringBuilder 512 [RpaPick.PickW32]::GetWindowTextW([IntPtr]$h, $sb, 512) | Out-Null if ($sb.ToString()) { $rootName = $sb.ToString(); break } } $anc = $walker.GetParent($anc) } $ctrlName = $c.ControlType.ProgrammaticName.Replace("ControlType.", "") $result = @{ window = $rootName; name = $c.Name; automationId = $c.AutomationId; controlType = $ctrlName; className = $c.ClassName } break } $prevDown = $down Start-Sleep -Milliseconds 80 } $form.Close() if ($result) { Write-Output (ConvertTo-Json $result -Compress) } else { Write-Output (ConvertTo-Json @{ cancelled = $true } -Compress) }