键盘输入转义逻辑移到 JS 侧根治脚本语法错误

This commit is contained in:
yu 2026-11-04 09:14:09 +08:00
parent f390db9c94
commit bb03699cce
2 changed files with 28 additions and 8 deletions

View File

@ -135,6 +135,11 @@ export function psString(value: unknown): string {
return `'${String(value ?? "").replace(/'/g, "''")}'`;
}
/** 把 SendKeys 特殊字符按字面转义(+^%~(){}[] → {+} 等);SendKeys 用花括号表示字面量 */
function sendKeysEscape(ch: string): string {
return "+^%~(){}[]".includes(ch) ? `{${ch}}` : ch;
}
const keyboardSend: CapabilityHandler = async (_ctx, node, args) => {
// 字段: words=输入内容(键盘输入), keys/key=按键组合(按键系列), interval=输入间隔(V1毫秒/基础版秒), fuctype=输入方式(0后台接口/1人工模拟/2剪贴板粘贴), window_title=输入目标窗口(留空=当前焦点窗口)
const keys = text(args, ["words", "keys", "key", "text", "value"]);
@ -144,17 +149,26 @@ const keyboardSend: CapabilityHandler = async (_ctx, node, args) => {
const intervalMs = node.componentId === "Keyboard_Send" ? Math.max(0, Math.round(rawInterval * 1000)) : Math.max(0, Math.round(rawInterval));
const mode = text(args, ["fuctype"], "0");
const isTextSend = node.componentId === "Keyboard_Send" || node.componentId === "Keyboard_Send_V1";
// 文本输入需转义 SendKeys 特殊字符(+^%~(){}[])按字面输入;按键组合组件(Keyboard_Press)与粘贴模式保留原文
const escape = isTextSend && mode !== "2" ? `$t = $t -replace '[+^%~(){}[\\]]','{$0}'; ` : "";
const send = mode === "2"
? `Set-Clipboard -Value $t; Start-Sleep -Milliseconds 120; [System.Windows.Forms.SendKeys]::SendWait('^v')`
: mode === "1"
? `foreach ($ch in $t.ToCharArray()) { $c = [string]$ch; if ('+^%~(){}[]'.Contains($c)) { $c = '{' + $c + '}' }; [System.Windows.Forms.SendKeys]::SendWait($c); Start-Sleep -Milliseconds ${intervalMs} }`
: `[System.Windows.Forms.SendKeys]::SendWait($t)`;
// 指定目标窗口时先激活再输入,内容才会进到目标窗口而不是运行时的焦点窗口
const targetTitle = text(args, ["window_title", "target_window", "window_obj", "match_title", "select_title"]);
const activate = targetTitle ? `${activateWindowScript(targetTitle)}; Start-Sleep -Milliseconds 300; ` : "";
await powershell(`${USER32}; ${activate}Add-Type -AssemblyName System.Windows.Forms; $t = ${psString(keys)}; ${escape}${send}`);
// 三种输入方式:脚本尽量简单,转义逻辑放 JS 侧,避免 PowerShell 字符串拼接的语法陷阱
let send: string;
if (mode === "2") {
// 剪贴板粘贴:原文进剪贴板 + Ctrl+V,不做 SendKeys 转义
send = `Set-Clipboard -Value ${psString(keys)}; Start-Sleep -Milliseconds 120; [System.Windows.Forms.SendKeys]::SendWait('^v')`;
} else if (mode === "1" && isTextSend) {
// 人工模拟:逐字符;JS 侧把每个字符转义成 SendKeys 字面量(含单引号用 '' 转义),PS 侧只做数组循环
const escapedChars = Array.from(keys).map((ch) => sendKeysEscape(ch).replace(/'/g, "''"));
const arr = escapedChars.map((c) => `'${c}'`).join(",");
send = `$chars = @(${arr}); foreach ($c in $chars) { [System.Windows.Forms.SendKeys]::SendWait($c); Start-Sleep -Milliseconds ${intervalMs} }`;
} else {
// 后台接口 / 按键组合 / 人工模拟(按键组合组件):整段发送,文本特殊字符转义
const escaped = isTextSend ? Array.from(keys).map(sendKeysEscape).join("") : keys;
send = `[System.Windows.Forms.SendKeys]::SendWait(${psString(escaped)})`;
}
await powershell(`${USER32}; ${activate}Add-Type -AssemblyName System.Windows.Forms; ${send}`);
await manualDelay();
return keys;
};

View File

@ -32,6 +32,12 @@ describe("键盘输入组件真实冒烟", () => {
console.log("[键盘输入] 人工模拟逐字符 ✓:", out);
}, 60000);
it("人工模拟模式含撇号与特殊字符(用户 09:05 踩坑场景)不抛语法错", async () => {
const out = await invoke("Keyboard_Send_V1", { words: "hhhhh' +^%~(){}[]", interval: "10", fuctype: "1" });
expect(out).toBe("hhhhh' +^%~(){}[]");
console.log("[键盘输入] 人工模拟+撇号+特殊字符 ✓:", out);
}, 60000);
it("剪切板粘贴模式: 原文进入剪贴板并发送 Ctrl+V", async () => {
const content = `粘贴${Date.now()}`;
const out = await invoke("Keyboard_Send_V1", { words: content, fuctype: "2" });