键盘输入转义逻辑移到 JS 侧根治脚本语法错误
This commit is contained in:
parent
f390db9c94
commit
bb03699cce
@ -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;
|
||||
};
|
||||
|
||||
@ -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" });
|
||||
|
||||
Loading…
Reference in New Issue
Block a user