From ed9b9daa509e4844e7b171b1cfdcf6832dff1d84 Mon Sep 17 00:00:00 2001 From: yu <191972707@qq.com> Date: Fri, 30 Oct 2026 12:01:01 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=8B=BE=E5=8F=96=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E5=AE=8C=E6=95=B4=E9=87=8D=E5=86=99=E2=80=94=E2=80=94v3=20?= =?UTF-8?q?=E9=80=BB=E8=BE=91+=E5=85=A8=E9=93=BE=E8=B7=AF=E6=97=A5?= =?UTF-8?q?=E5=BF=97=EF=BC=88=E6=AD=A4=E5=89=8D=E9=AA=A8=E6=9E=B6=E8=A6=86?= =?UTF-8?q?=E7=9B=96=E4=BA=8B=E6=95=85=E4=BF=AE=E5=A4=8D=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/desktop-picker.ps1 | 147 +++++++++++++++-------------------- 1 file changed, 62 insertions(+), 85 deletions(-) diff --git a/resources/desktop-picker.ps1 b/resources/desktop-picker.ps1 index 61c97c4..ebdf5ae 100644 --- a/resources/desktop-picker.ps1 +++ b/resources/desktop-picker.ps1 @@ -1,28 +1,29 @@ param([string]$Mode = "element") -$ErrorActionPreference = "Continue" +$ErrorActionPreference = "Continue"; +$logPath = "D:/RPA/test-output/desktop-picker.log"; +function Write-PickLog([string]$msg) { + try { Add-Content -Path $logPath -Value ((Get-Date -Format "HH:mm:ss.fff") + " | " + $msg) -Encoding UTF8 } catch {} +} +Write-PickLog ("=== start Mode=$Mode ===") Add-Type -AssemblyName UIAutomationClient, UIAutomationTypes, WindowsBase 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 - +Write-PickLog "assemblies ok" +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 +Write-PickLog "w32 ok" 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 } - } - } + foreach ($p in Get-Process) { if ($p.MainWindowHandle -ne [IntPtr]::Zero -and $p.MainWindowTitle) { $wins += @{ title = $p.MainWindowTitle; process = $p.ProcessName } } } + Write-PickLog "windows: $($_wins.Count)" Write-Output (ConvertTo-Json $wins -Compress -AsArray) exit 0 } - -# ===== 信息条(屏幕顶部居中,显眼) ===== $info = New-Object System.Windows.Forms.Form $info.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::None $info.TopMost = $true $info.ShowInTaskbar = $false $info.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual -$sw = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Width -$info.Location = New-Object System.Drawing.Point(([int]($sw / 2) - 280), 10) +$sw2 = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Width +$info.Location = New-Object System.Drawing.Point(([int]($sw2 / 2) - 280), 10) $info.Size = New-Object System.Drawing.Size(560, 64) $info.BackColor = [System.Drawing.Color]::FromArgb(15, 40, 90) $info.Opacity = 0.92 @@ -33,8 +34,6 @@ $infoLabel.Font = New-Object System.Drawing.Font("Microsoft YaHei", 11) $infoLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter $infoLabel.Text = "移动鼠标到目标元素上" $info.Controls.Add($infoLabel) - -# ===== 高亮框(半透明红块跟随) ===== $hl = New-Object System.Windows.Forms.Form $hl.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::None $hl.TopMost = $true @@ -42,14 +41,12 @@ $hl.ShowInTaskbar = $false $hl.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual $hl.BackColor = [System.Drawing.Color]::Red $hl.Opacity = 0.35 - function Set-HighlightBox([int]$x, [int]$y, [int]$w, [int]$h) { $hl.Location = New-Object System.Drawing.Point(($x - 2), ($y - 2)) $hl.Size = New-Object System.Drawing.Size(($w + 4), ($h + 4)) $hl.Show() } - -# ===== 下钻到包含点的最小后代 ===== +function Hide-Highlight { $hl.Hide() } function Get-DeepestAtPoint([double]$px, [double]$py) { $point = New-Object System.Windows.Automation.Point($px, $py) $cur = [System.Windows.Automation.AutomationElement]::FromPoint($point) @@ -72,89 +69,69 @@ function Get-DeepestAtPoint([double]$px, [double]$py) { } return $cur } - $info.Show() -$hl.Show() - $stage = "hover" $chain = New-Object System.Collections.ArrayList $selIdx = -1 -$script:lastX = -1 -$script:lastY = -1 -$script:lastMove = Get-Date -$script:pending = $false $prevSpace = $false $prevPgUp = $false $prevPgDn = $false - +Write-PickLog "loop start" while ($true) { - $space = ([RpaPick.PickW32]::GetAsyncKeyState(32) -band 0x8000) -ne 0 - $esc = ([RpaPick.PickW32]::GetAsyncKeyState(27) -band 0x8000) -ne 0 - $pgUp = ([RpaPick.PickW32]::GetAsyncKeyState(33) -band 0x8000) -ne 0 - $pgDn = ([RpaPick.PickW32]::GetAsyncKeyState(34) -band 0x8000) -ne 0 - - if ($esc) { break } - - if ($stage -eq "hover") { - $ptX = [System.Windows.Forms.Cursor]::Position.X - $ptY = [System.Windows.Forms.Cursor]::Position.Y - if ($ptX -ne $script:lastX -or $ptY -ne $script:lastY) { - $script:lastX = $ptX; $script:lastY = $ptY - $script:lastMove = Get-Date - $script:pending = $true - } - $idle = ((Get-Date) - $script:lastMove).TotalMilliseconds -ge 250 - if (-not $idle) { Start-Sleep -Milliseconds 60; return } - $el = Get-DeepestAtPoint $ptX $ptY - if ($el) { - $c = $el.Current - $ctrlName = $c.ControlType.ProgrammaticName.Replace("ControlType.", "") - Set-HighlightBox $ptX $ptY 1 1 - $r = $c.Current.BoundingRectangle - if ($r.Width -gt 0) { Set-HighlightBox ([int]$r.X) ([int]$r.Y) ([int]$r.Width) ([int]$r.Height) } - $infoLabel.Text = "名称: " + $c.Name + " 类型: " + $ctrlName + " [空格]锁定 [Esc]取消" - } - if ($space -and -not $prevSpace -and $el) { - $stage = "locked" - $chain = New-Object System.Collections.ArrayList - $walker = [System.Windows.Automation.TreeWalker]::ControlViewWalker - $cur = $el - while ($cur -and -not $cur.Equals([System.Windows.Automation.AutomationElement]::RootElement)) { - $c = $cur.Current - $r = $c.BoundingRectangle - [void]$chain.Insert(0, @{ el = $cur; name = [string]$c.Name; automationId = [string]$c.AutomationId; controlType = $c.ControlType.ProgrammaticName.Replace("ControlType.", ""); x = [int]$r.X; y = [int]$r.Y; w = [int]$r.Width; h = [int]$r.Height }) - $cur = $walker.GetParent($cur) + try { + $space = ([RpaPick.PickW32]::GetAsyncKeyState(32) -band 0x8000) -ne 0 + $esc = ([RpaPick.PickW32]::GetAsyncKeyState(27) -band 0x8000) -ne 0 + $pgUp = ([RpaPick.PickW32]::GetAsyncKeyState(33) -band 0x8000) -ne 0 + $pgDn = ([RpaPick.PickW32]::GetAsyncKeyState(34) -band 0x8000) -ne 0 + if ($esc) { Write-PickLog "esc"; break } + if ($stage -eq "hover") { + $ptX = [System.Windows.Forms.Cursor]::Position.X + $ptY = [System.Windows.Forms.Cursor]::Position.Y + $el = Get-DeepestAtPoint $ptX $ptY + if ($el) { + $c = $el.Current + $ctrlName = $c.ControlType.ProgrammaticName.Replace("ControlType.", "") + Set-HighlightBox ([int]$c.Current.BoundingRectangle.X) ([int]$c.Current.BoundingRectangle.Y) ([int]$c.Current.BoundingRectangle.Width) ([int]$c.Current.BoundingRectangle.Height) + $infoLabel.Text = "名称: " + $c.Name + " 类型: " + $ctrlName + " [空格]锁定 [Esc]取消" + } else { Hide-Highlight } + if ($space -and -not $prevSpace -and $el) { + Write-PickLog "space lock" + $stage = "locked" + $chain = New-Object System.Collections.ArrayList + $walker = [System.Windows.Automation.TreeWalker]::ControlViewWalker + $cur = $el + while ($cur -and -not $cur.Equals([System.Windows.Automation.AutomationElement]::RootElement)) { + $c = $cur.Current + $r = $c.BoundingRectangle + [void]$chain.Insert(0, @{ el = $cur; name = [string]$c.Name; automationId = [string]$c.AutomationId; controlType = $c.ControlType.ProgrammaticName.Replace("ControlType.", ""); x = [int]$r.X; y = [int]$r.Y; w = [int]$r.Width; h = [int]$r.Height }) + $cur = $walker.GetParent($cur) + } + $selIdx = $chain.Count - 1 + Write-PickLog ("locked chain=" + $chain.Count) + $infoLabel.Text = "已锁定 [" + ($selIdx + 1) + "/" + $chain.Count + "] [PageUp/PageDown]调层级 [空格]确认回填 [Esc]取消" } - $selIdx = $chain.Count - 1 - $infoLabel.Text = "已锁定 [" + ($selIdx + 1) + "/" + $chain.Count + "] [PageUp/PageDown]调层级 [空格]确认回填 [Esc]取消" } - } - - if ($stage -eq "locked") { - $item = $chain[$selIdx] - if ($item) { - Set-HighlightBox $item.x $item.y $item.w $item.h - $infoLabel.Text = "层级 " + ($selIdx + 1) + "/" + $chain.Count + " 名称: " + $item.name + " 类型: " + $item.controlType + " [PageUp/PageDown]调层级 [空格]确认 [Esc]取消" - } - if ($pgUp -and -not $prevPgUp -and $selIdx -gt 0) { $selIdx -= 1 } - if ($pgDn -and -not $prevPgDn -and $selIdx -lt ($chain.Count - 1)) { $selIdx += 1 } - if ($space -and -not $prevSpace) { + if ($stage -eq "locked") { $item = $chain[$selIdx] - $rootTitle = "" - foreach ($it in $chain) { if ($it.name) { $rootTitle = $it.name; break } } - $result = @{ selected = $selIdx; window = $rootTitle; name = $item.name; automationId = $item.automationId; controlType = $item.controlType; x = $item.x; y = $item.y; w = $item.w; h = $item.h } - break + if ($item) { + Set-HighlightBox $item.x $item.y $item.w $item.h + $infoLabel.Text = "层级 " + ($selIdx + 1) + "/" + $chain.Count + " 名称: " + $item.name + " 类型: " + $item.controlType + " [PageUp/PageDown]调层级 [空格]确认 [Esc]取消" + } + if ($pgUp -and -not $prevPgUp -and $selIdx -gt 0) { $selIdx -= 1 } + if ($pgDn -and -not $prevPgDn -and $selIdx -lt ($chain.Count - 1)) { $selIdx += 1 } + if ($space -and -not $prevSpace) { + $item = $chain[$selIdx] + $rootTitle = "" + foreach ($it in $chain) { if ($it.name) { $rootTitle = $it.name; break } } + $result = @{ selected = $selIdx; window = $rootTitle; name = $item.name; automationId = $item.automationId; controlType = $item.controlType; x = $item.x; y = $item.y; w = $item.w; h = $item.h } + break + } } + } catch { + Write-PickLog ("LOOP ERR: " + $_.Exception.Message) } - - $prevSpace = $space - $prevPgUp = $pgUp - $prevPgDn = $pgDn - [System.Windows.Forms.Application]::DoEvents() Start-Sleep -Milliseconds 60 } - $info.Close() $hl.Close() - if ($result) { Write-Output (ConvertTo-Json $result -Compress) } else { Write-Output (ConvertTo-Json @{ cancelled = $true } -Compress) } \ No newline at end of file