Compare commits
8
Commits
2b372e2d7f
...
69e9554250
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69e9554250 | ||
|
|
7c7a1b1a1f | ||
|
|
9d996f137b | ||
|
|
06981dfff3 | ||
|
|
093fc302fa | ||
|
|
3b05d10ff4 | ||
|
|
9c973d9bad | ||
|
|
2c32a8f51d |
No files matched your search
@@ -52,7 +52,10 @@ export function parseUiaSelector(raw: unknown): UiaSelector {
|
||||
return selector;
|
||||
}
|
||||
|
||||
const UIA_USING = "Add-Type -AssemblyName UIAutomationClient, UIAutomationTypes;";
|
||||
const UIA_USING = [
|
||||
"Add-Type -AssemblyName UIAutomationClient, UIAutomationTypes;",
|
||||
"try { Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern bool SetProcessDpiAwarenessContext(IntPtr value);' -Name RpaDpi -Namespace WinRpaDpi | Out-Null; [WinRpaDpi.RpaDpi]::SetProcessDpiAwarenessContext([IntPtr](-4)) | Out-Null } catch {}"
|
||||
].join("\n");
|
||||
|
||||
const FIND_HELPER = `
|
||||
function Find-RpaWindow([string]$winName) {
|
||||
@@ -60,8 +63,29 @@ function Find-RpaWindow([string]$winName) {
|
||||
if (-not $winName) { return $root }
|
||||
$cond = New-Object System.Windows.Automation.PropertyCondition([System.Windows.Automation.AutomationElement]::NameProperty, $winName)
|
||||
$win = $root.FindFirst([System.Windows.Automation.TreeScope]::Children, $cond)
|
||||
if (-not $win) { throw "window_not_found:$winName" }
|
||||
return $win
|
||||
if ($win) { return $win }
|
||||
Add-RpaUser32
|
||||
$script:hitHwnd = [IntPtr]::Zero
|
||||
$cb = [WinRpa.RpaUser32Click+EnumProc]{ param($h, $l)
|
||||
$sb = New-Object System.Text.StringBuilder 256
|
||||
[WinRpa.RpaUser32Click]::GetWindowTextW($h, $sb, 256) | Out-Null
|
||||
if ($sb.ToString() -eq $winName) { $script:hitHwnd = $h; return $false }
|
||||
return $true
|
||||
}
|
||||
[WinRpa.RpaUser32Click]::EnumWindows($cb, [IntPtr]::Zero) | Out-Null
|
||||
if ($script:hitHwnd -ne [IntPtr]::Zero) {
|
||||
[WinRpa.RpaUser32Click]::ShowWindow($script:hitHwnd, 9) | Out-Null
|
||||
Start-Sleep -Milliseconds 500
|
||||
$sw2 = [WinRpa.RpaUser32Click]::GetSystemMetrics(0)
|
||||
$sh2 = [WinRpa.RpaUser32Click]::GetSystemMetrics(1)
|
||||
$w2 = [Math]::Min(1400, $sw2 - 120)
|
||||
$h2 = [Math]::Min(820, $sh2 - 120)
|
||||
[WinRpa.RpaUser32Click]::SetWindowPos($script:hitHwnd, [IntPtr]::Zero, 60, 60, $w2, $h2, 0x0040) | Out-Null
|
||||
Start-Sleep -Milliseconds 600
|
||||
$win = $root.FindFirst([System.Windows.Automation.TreeScope]::Children, $cond)
|
||||
if ($win) { return $win }
|
||||
}
|
||||
throw "window_not_found:$winName"
|
||||
}
|
||||
function Find-RpaElement($parent, [string]$name, [string]$id, [string]$type, [string]$className, [int]$index) {
|
||||
$conds = @()
|
||||
@@ -80,7 +104,7 @@ function Find-RpaElement($parent, [string]$name, [string]$id, [string]$type, [st
|
||||
return $all[$pick - 1]
|
||||
}
|
||||
function Add-RpaUser32 {
|
||||
Add-Type -MemberDefinition '[DllImport("user32.dll")] public static extern bool SetCursorPos(int X, int Y); [DllImport("user32.dll")] public static extern void mouse_event(uint flags, uint dx, uint dy, uint data, UIntPtr extra); [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd);' -Name RpaUser32Click -Namespace Win32Rpa | Out-Null
|
||||
Add-Type -MemberDefinition '[DllImport("user32.dll")] public static extern bool SetCursorPos(int X, int Y); [DllImport("user32.dll")] public static extern void mouse_event(uint flags, uint dx, uint dy, uint data, UIntPtr extra); [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr after, int X, int Y, int cx, int cy, uint flags); [DllImport("user32.dll")] public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach); [DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); [DllImport("kernel32.dll")] public static extern uint GetCurrentThreadId(); [DllImport("user32.dll")] public static extern int GetSystemMetrics(int nIndex); [DllImport("user32.dll")] public static extern bool EnumWindows(EnumProc cb, IntPtr lp); public delegate bool EnumProc(IntPtr hWnd, IntPtr lp); [DllImport("user32.dll", CharSet = CharSet.Unicode)] public static extern int GetWindowTextW(IntPtr hWnd, System.Text.StringBuilder sb, int max);' -Name RpaUser32Click -Namespace Win32Rpa | Out-Null
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -143,7 +167,37 @@ try {
|
||||
} catch { $el = $null }
|
||||
if ($null -eq $el) { Write-Output "JSON_NOT_FOUND"; exit 0 }
|
||||
$rect = $el.Current.BoundingRectangle
|
||||
$offscreen = $el.Current.IsOffscreen -or $rect.Width -le 0 -or $rect.Height -le 0
|
||||
Add-RpaUser32
|
||||
$vsX = [WinRpa.RpaUser32Click]::GetSystemMetrics(76)
|
||||
$vsY = [WinRpa.RpaUser32Click]::GetSystemMetrics(77)
|
||||
$vsW = [WinRpa.RpaUser32Click]::GetSystemMetrics(78)
|
||||
$vsH = [WinRpa.RpaUser32Click]::GetSystemMetrics(79)
|
||||
$inVs = ($rect.X -ge $vsX) -and ($rect.Y -ge $vsY) -and (($rect.X + $rect.Width) -le ($vsX + $vsW)) -and (($rect.Y + $rect.Height) -le ($vsY + $vsH))
|
||||
$offscreen = $el.Current.IsOffscreen -or $rect.Width -le 0 -or $rect.Height -le 0 -or (-not $inVs)
|
||||
if ($offscreen) {
|
||||
# 窗口可能被最小化或移出屏幕:还原并移回可视区后重取坐标
|
||||
$walker0 = [System.Windows.Automation.TreeWalker]::ControlViewWalker
|
||||
$anc0 = $el
|
||||
$topHwnd = [IntPtr]::Zero
|
||||
while ($null -ne $anc0) {
|
||||
$h0 = $anc0.Current.NativeWindowHandle
|
||||
if ($h0 -ne 0) { $topHwnd = [IntPtr]$h0; break }
|
||||
$anc0 = $walker0.GetParent($anc0)
|
||||
}
|
||||
if ($topHwnd -ne [IntPtr]::Zero) {
|
||||
[WinRpa.RpaUser32Click]::ShowWindow($topHwnd, 9) | Out-Null
|
||||
Start-Sleep -Milliseconds 600
|
||||
$sw3 = [WinRpa.RpaUser32Click]::GetSystemMetrics(0)
|
||||
$sh3 = [WinRpa.RpaUser32Click]::GetSystemMetrics(1)
|
||||
$w3 = [Math]::Min(1400, $sw3 - 120)
|
||||
$h3 = [Math]::Min(820, $sh3 - 120)
|
||||
[WinRpa.RpaUser32Click]::SetWindowPos($topHwnd, [IntPtr]::Zero, 60, 60, $w3, $h3, 0x0040) | Out-Null
|
||||
Start-Sleep -Milliseconds 600
|
||||
$rect = $el.Current.BoundingRectangle
|
||||
$inVs = ($rect.X -ge $vsX) -and ($rect.Y -ge $vsY) -and (($rect.X + $rect.Width) -le ($vsX + $vsW)) -and (($rect.Y + $rect.Height) -le ($vsY + $vsH))
|
||||
$offscreen = $el.Current.IsOffscreen -or $rect.Width -le 0 -or $rect.Height -le 0 -or (-not $inVs)
|
||||
}
|
||||
}
|
||||
$method = "coordinate_click"
|
||||
$ok = $false
|
||||
if (-not $offscreen) {
|
||||
@@ -156,7 +210,18 @@ if (-not $offscreen) {
|
||||
if ($h -ne 0) { $hwnd = [IntPtr]$h; break }
|
||||
$ancestor = $walker.GetParent($ancestor)
|
||||
}
|
||||
if ($hwnd -ne [IntPtr]::Zero) { [WinRpa.RpaUser32Click]::SetForegroundWindow($hwnd) | Out-Null; Start-Sleep -Milliseconds 250 }
|
||||
if ($hwnd -ne [IntPtr]::Zero) {
|
||||
$fgHwnd = [WinRpa.RpaUser32Click]::GetForegroundWindow()
|
||||
if ($fgHwnd -ne $hwnd) {
|
||||
$fgPid = [uint32]0
|
||||
$fgThread = [WinRpa.RpaUser32Click]::GetWindowThreadProcessId($fgHwnd, [ref]$fgPid)
|
||||
$thisThread = [WinRpa.RpaUser32Click]::GetCurrentThreadId()
|
||||
[WinRpa.RpaUser32Click]::AttachThreadInput($thisThread, $fgThread, $true) | Out-Null
|
||||
[WinRpa.RpaUser32Click]::SetForegroundWindow($hwnd) | Out-Null
|
||||
[WinRpa.RpaUser32Click]::AttachThreadInput($thisThread, $fgThread, $false) | Out-Null
|
||||
}
|
||||
Start-Sleep -Milliseconds 250
|
||||
}
|
||||
$x = [int]($rect.X + $rect.Width / 2)
|
||||
$y = [int]($rect.Y + $rect.Height / 2)
|
||||
[WinRpa.RpaUser32Click]::SetCursorPos($x, $y) | Out-Null
|
||||
@@ -189,13 +254,14 @@ if (-not $offscreen) {
|
||||
$rect2 = $el.Current.BoundingRectangle
|
||||
Write-Output (@{ clicked = $ok; method = $method; name = $el.Current.Name; x = [int]$rect2.X; y = [int]$rect2.Y; w = [int]$rect2.Width; h = [int]$rect2.Height } | ConvertTo-Json -Compress)`;
|
||||
}
|
||||
function setValueScript(t: UiaTarget, value: string): string {
|
||||
export function setValueScript(t: UiaTarget, value: string): string {
|
||||
const s = t.selector;
|
||||
return `${UIA_USING}
|
||||
${FIND_HELPER}
|
||||
try {
|
||||
$parent = Find-RpaWindow ${psString(s.window ?? "")}
|
||||
$el = Find-RpaElement $parent ${psString(s.name ?? "")} ${psString(s.id ?? "")} ${psString(s.type ?? "")} ${psString(s.className ?? "")} ${s.index}
|
||||
} catch { $el = $null }
|
||||
if ($null -eq $el) { Write-Output "JSON_NOT_FOUND"; exit 0 }
|
||||
$value = ${psString(value)}
|
||||
$method = "value_pattern"
|
||||
@@ -232,6 +298,7 @@ ${FIND_HELPER}
|
||||
try {
|
||||
$parent = Find-RpaWindow ${psString(s.window ?? "")}
|
||||
$el = Find-RpaElement $parent ${psString(s.name ?? "")} ${psString(s.id ?? "")} ${psString(s.type ?? "")} ${psString(s.className ?? "")} ${s.index}
|
||||
} catch { $el = $null }
|
||||
if ($null -eq $el) { Write-Output "JSON_NOT_FOUND"; exit 0 }
|
||||
$value = $el.Current.Name
|
||||
try { $vp = $el.GetCurrentPattern([System.Windows.Automation.ValuePattern]::Pattern); $value = $vp.Value } catch {}
|
||||
@@ -320,3 +387,9 @@ register("Element_WaitElementGround", waitElementGround);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -122,7 +122,8 @@ const runApp: CapabilityHandler = async (_ctx, node, args) => {
|
||||
if (!executable) throw new RuntimeError("validation_error", "应用路径为空", { nodeId: node.id, componentId: node.componentId });
|
||||
const params = text(args, ["params", "arguments"]);
|
||||
const cwd = text(args, ["cwd"]);
|
||||
const result = await powershell(`$p = Start-Process -FilePath ${psString(executable)} -ArgumentList ${psString(params)} ${cwd ? `-WorkingDirectory ${psString(cwd)}` : ""} -PassThru; $p.Id`);
|
||||
const argPart = params ? ` -ArgumentList ${psString(params)}` : "";
|
||||
const result = await powershell(`$p = Start-Process -FilePath ${psString(executable)}${argPart} ${cwd ? `-WorkingDirectory ${psString(cwd)}` : ""} -PassThru; $p.Id`);
|
||||
return Number(result) || result;
|
||||
};
|
||||
|
||||
@@ -161,3 +162,4 @@ register("Clipboard_SetText", clipboardSet);
|
||||
register("Dialog_Notice", notice);
|
||||
register("Dialog_MsgBox", notice);
|
||||
register("System_ExecuteCommand", executeCommand);
|
||||
|
||||
@@ -175,6 +175,7 @@ export function listFlows(): FlowSummary[] {
|
||||
const runs = latestRuns();
|
||||
for (const entry of fs.readdirSync(base)) {
|
||||
if (!entry.endsWith(".json")) continue;
|
||||
if (/-pre-|\\.bak/i.test(entry)) continue;
|
||||
try {
|
||||
const flow = JSON.parse(fs.readFileSync(path.join(base, entry), "utf8")) as FlowDefinition;
|
||||
if (!flow?.id || !Array.isArray(flow.nodes)) continue;
|
||||
@@ -231,3 +232,4 @@ export function deleteFlow(id: string): void {
|
||||
const target = fileOf(id);
|
||||
if (fs.existsSync(target)) fs.unlinkSync(target);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user