import { register } from "../engine/registry"; import { RuntimeError } from "../engine/types"; import { execFile } from "node:child_process"; import { promisify } from "node:util"; const run = promisify(execFile); const ps = (script: string) => run("powershell.exe", ["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", script], { windowsHide: true, timeout: 60000 }); function reqText(args: Record, keys: string[], label: string, nodeId: string): string { for (const key of keys) { const v = String(args[key] ?? "").trim(); if (v) return v; } throw new RuntimeError("validation_error", label + "为空", { nodeId, componentId: nodeId }); } register("ScreenControl_Screenlock", async () => { await run("rundll32.exe", ["user32.dll,LockWorkStation"], { windowsHide: true }); return { locked: true }; }); register("ScreenControl_ScreenUnlock", async () => { // 仅唤醒屏幕/解除屏保;系统锁屏需人工输入密码,无法通用自动解锁 await ps("Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern void mouse_event(uint f, uint dx, uint dy, uint d, UIntPtr e);' -Name W32U -Namespace WinRpa | Out-Null; [WinRpa.W32U]::mouse_event(0x0001, 1, 1, 0, [UIntPtr]::Zero); Start-Sleep -Milliseconds 200; [WinRpa.W32U]::mouse_event(0x0001, 0xFFFFFFFF, 0, 0, [UIntPtr]::Zero)"); return { awakened: true, note: "已唤醒屏幕;锁屏需人工输入密码" }; }); const SC_SCREENSAVE = 0xF140; const WM_SYSCOMMAND = 0x0112; register(["System_ScreenSaverShow", "System_ScreenSaverShowV1"], async () => { await ps("Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern IntPtr FindWindow(string cls, string win); [DllImport(\"user32.dll\")] public static extern IntPtr SendMessage(IntPtr h, uint m, IntPtr w, IntPtr l);' -Name W32S -Namespace WinRpa | Out-Null; [WinRpa.W32S]::SendMessage([IntPtr]0xFFFF, [UIntPtr]0x0112, [IntPtr]0xF140, [IntPtr]::Zero) | Out-Null"); return { screensaver: true }; }); register("System_ScreenSaverStop", async () => { await ps("Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern IntPtr FindWindow(string cls, string win); [DllImport(\"user32.dll\")] public static extern bool PostMessage(IntPtr h, uint m, IntPtr w, IntPtr l);' -Name W32P -Namespace WinRpa | Out-Null; $h = [WinRpa.W32P]::FindWindow('WindowsScreenSaverClass', $null); if ($h -ne [IntPtr]::Zero) { [WinRpa.W32P]::PostMessage($h, 0x0010, [IntPtr]::Zero, [IntPtr]::Zero) | Out-Null }"); return { stopped: true }; }); register("System_ReadCredential", async (ctx, node, args) => { const app = reqText(args, ["application"], "凭据目标", node.id); const { stdout } = await run("cmdkey", ["/list"], { windowsHide: true }); const exists = stdout.includes(app); const userLine = stdout.split(/\r?\n/).find(l => l.includes(app)); return { target: app, exists, detail: exists ? (userLine ?? "").trim() : "" }; }); register("System_AddCredential", async (ctx, node, args) => { const app = reqText(args, ["application"], "凭据目标", node.id); const user = reqText(args, ["name"], "用户名", node.id); const pwd = String(args.password ?? ""); const psArgs = pwd ? ["/generic:" + app, "/user:" + user, "/pass:" + pwd] : ["/generic:" + app, "/user:" + user]; await run("cmdkey", psArgs, { windowsHide: true }); return { added: true, target: app }; }); register("System_DeleteCredential", async (ctx, node, args) => { const app = reqText(args, ["application"], "凭据目标", node.id); await run("cmdkey", ["/delete:" + app], { windowsHide: true }); return { deleted: true, target: app }; }); register("System_ConnectRemoteDesktop", async (ctx, node, args) => { const ip = reqText(args, ["ip"], "远程地址", node.id); const port = String(args.port ?? "").trim(); const target = port ? ip + ":" + port : ip; await run("mstsc.exe", ["/v:" + target], { windowsHide: true }); return { connected: true, target }; }); register("System_CloseRemoteDesktop", async () => { await run("tsdiscon.exe", [], { windowsHide: true }); return { disconnected: true }; }); register("System_GetInputMethodState", async () => { const { stdout } = await ps("Add-Type -AssemblyName System.Windows.Forms | Out-Null; $cur = [System.Windows.Forms.InputLanguage]::CurrentInputLanguage; Write-Output ($cur.Culture.Name + '|' + $cur.LayoutName)"); const [culture, layout] = stdout.split("|"); return { culture, layout }; }); register("System_SetInputMethodState", async (ctx, node, args) => { const mode = reqText(args, ["mode"], "输入法文化名", node.id); await ps("Add-Type -AssemblyName System.Windows.Forms | Out-Null; $lang = [System.Windows.Forms.InputLanguage]::FromCulture('" + mode.replace(/'/g, "''") + "'); if ($lang) { [System.Windows.Forms.InputLanguage]::CurrentInputLanguage = $lang }"); return { set: true, mode }; }); register("File_OpenFile", async (ctx, node, args) => { const p = reqText(args, ["path"], "文件夹路径", node.id); await run("explorer.exe", [p], { windowsHide: true }); return { opened: true, path: p }; });