From 20d224a46b022e64598cf49f8dbbc6e441e6916f Mon Sep 17 00:00:00 2001 From: yu <191972707@qq.com> Date: Thu, 5 Nov 2026 11:27:01 +0800 Subject: [PATCH] fix: input dialog invisible - replace VB InputBox with topmost WinForms form MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause of second failure (120s timeout): VB InputBox has no topmost flag and no taskbar presence, so it renders BEHIND the main window. User never sees it, flow waits until node timeout (120000ms). Fix: - Dialog_InputBox now builds a WinForms form with TopMost=true, ShowInTaskbar=true, CenterScreen, OK/Cancel buttons - MessageBox notice adds MB_TOPMOST via options param - Flow updated: 3 sequential InputBox nodes replaced by ONE Dialog_GetConfigV7 form (topmost BrowserWindow via host bridge), 3 fields filled in a single window, wait_time=10min - Flow node timeout raised to 660s to exceed the 600s PS-level wait - Fixed latent bug: Time_WeekDay node had empty outputVar, so the "星期几" variable never existed --- packages/rpa-core/src/capabilities/desktop.ts | 48 ++++++++++++++++--- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/packages/rpa-core/src/capabilities/desktop.ts b/packages/rpa-core/src/capabilities/desktop.ts index e0b0acd..6e7a828 100644 --- a/packages/rpa-core/src/capabilities/desktop.ts +++ b/packages/rpa-core/src/capabilities/desktop.ts @@ -151,10 +151,10 @@ const clipboardSet: CapabilityHandler = async (_ctx, _node, args) => { const notice: CapabilityHandler = async (_ctx, _node, args) => { const title = text(args, ["title"], "提醒"); const content = text(args, ["text", "message"]); - // MessageBox 阻塞等用户点确定,同样不能吃 powershell() 默认 30s 超时;notice 组件的 timeout 参数按分钟级等待 + // MessageBox 阻塞等用户点确定,同样不能吃 powershell() 默认 30s 超时;且 MB_TOPMOST 保证弹窗不被主窗口盖住 const waitSeconds = number(args, ["wait_time", "waitTime", "timeout"], 600); const timeoutMs = Math.max(10000, Math.round(waitSeconds * 1000)); - await powershell(`Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show(${psString(content)},${psString(title)}) | Out-Null`, timeoutMs); + await powershell(`Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show(${psString(content)},${psString(title)},'OK','Information','Button1','HelpButton',1) | Out-Null`, timeoutMs); return true; }; @@ -231,12 +231,46 @@ register(["Dialog_InputBox", "Dialog_CsInputBox"], async (_ctx, _node, args) => // 默认 10 分钟,可用 wait_time(秒)自定义;仍超时则报「用户未及时输入」而非笼统的 Command failed。 const waitSeconds = number(args, ["wait_time", "waitTime", "timeout"], 600); const timeoutMs = Math.max(10000, Math.round(waitSeconds * 1000)); - return powershell( - "Add-Type -AssemblyName Microsoft.VisualBasic | Out-Null; [Microsoft.VisualBasic.Interaction]::InputBox(" + psString(description) + ", " + psString(title) + ", " + psString(defaultValue) + ")", - timeoutMs - ).catch((error) => { + // VB InputBox 不置顶也不在任务栏显示,容易被主窗口盖住导致"看不见弹窗→干等超时"。 + // 改用 WinForms 窗口:Topmost 强制置顶 + ShowInTaskbar + StartPosition 屏幕中央,保证用户一定看得见。 + const script = [ + "Add-Type -AssemblyName System.Windows.Forms | Out-Null", + "Add-Type -AssemblyName System.Drawing | Out-Null", + "$form = New-Object System.Windows.Forms.Form", + "$form.Text = " + psString(title), + "$form.Size = New-Object System.Drawing.Size(460, 240)", + "$form.StartPosition = 'CenterScreen'", + "$form.TopMost = $true", + "$form.ShowInTaskbar = $true", + "$form.FormBorderStyle = 'FixedDialog'", + "$form.MaximizeBox = $false", + "$label = New-Object System.Windows.Forms.Label", + "$label.Text = " + psString(description), + "$label.Location = New-Object System.Drawing.Point(14, 12)", + "$label.Size = New-Object System.Drawing.Size(416, 60)", + "$box = New-Object System.Windows.Forms.TextBox", + "$box.Text = " + psString(defaultValue), + "$box.Location = New-Object System.Drawing.Point(14, 78)", + "$box.Size = New-Object System.Drawing.Size(416, 26)", + "$ok = New-Object System.Windows.Forms.Button", + "$ok.Text = '确定'", + "$ok.DialogResult = [System.Windows.Forms.DialogResult]::OK", + "$ok.Location = New-Object System.Drawing.Point(256, 150)", + "$ok.Size = New-Object System.Drawing.Size(84, 30)", + "$form.AcceptButton = $ok", + "$cancel = New-Object System.Windows.Forms.Button", + "$cancel.Text = '取消'", + "$cancel.DialogResult = [System.Windows.Forms.DialogResult]::Cancel", + "$cancel.Location = New-Object System.Drawing.Point(346, 150)", + "$cancel.Size = New-Object System.Drawing.Size(84, 30)", + "$form.Controls.AddRange(@($label, $box, $ok, $cancel))", + "$form.Add_Shown({ $form.Activate() })", + "$result = $form.ShowDialog()", + "if ($result -eq [System.Windows.Forms.DialogResult]::OK) { $box.Text } else { '' }" + ].join("; "); + return powershell(script, timeoutMs).then((value) => ({ value, canceled: value === "" })).catch((error) => { if (error instanceof RuntimeError && /Command failed/.test(error.message) && !error.message.includes("RPA_ERROR")) { - throw new RuntimeError("dialog_timeout", `输入对话框等待超时(${Math.round(timeoutMs / 1000)} 秒)用户未完成输入`, { nodeId: _node.id, componentId: _node.componentId, recommendation: "在弹出的输入框中输入后点确定;如需更长等待时间,调大节点的超时时间或 wait_time 参数" }); + throw new RuntimeError("dialog_timeout", `输入对话框等待超时(${Math.round(timeoutMs / 1000)} 秒)用户未完成输入`, { nodeId: _node.id, componentId: _node.componentId, recommendation: "置顶输入框应显示在屏幕最前;若仍超时请调大节点的超时时间或 wait_time 参数" }); } throw error; });