You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止子进程模拟用户键盘输入或重定向其输入流?

解决子进程模拟回车键导致主程序提前退出的方案

方案1:重定向子进程的标准输入到空流

如果子进程是通过往自身标准输入写入回车键引发的问题,直接重定向它的标准输入并关闭,就能切断输入流向主进程控制台的路径。修改代码如下:

static void Main(string[] args)
{
    Process process = new Process();
    ProcessStartInfo startInfo = new ProcessStartInfo()
    {
        FileName = @"D:\PathTo\WorkerProcess.exe",
        Arguments = "-misc parameters",
        RedirectStandardOutput = true,
        RedirectStandardInput = true, // 开启标准输入重定向
        UseShellExecute = false,
        CreateNoWindow = true
    };
    process.StartInfo = startInfo;
    process.Start();
    
    // 关闭子进程的标准输入流,阻止它写入任何输入
    process.StandardInput.Close();
    
    process.WaitForExit(10000);
    string processConsoleOutput = process.StandardOutput.ReadToEnd();
    process.Close();

    Console.WriteLine("Press Enter to exit.");
    Console.ReadLine();
}

方案2:让子进程在独立桌面会话运行

如果子进程是调用Windows API(比如SendInput)直接向当前桌面发送全局键盘事件,重定向流就起不到作用了。这种情况下,可以给子进程创建一个独立的临时桌面,让它的输入完全隔离,不会影响主进程的控制台:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr CreateDesktop(string lpszDesktop, IntPtr lpszDevice, IntPtr pDevmode, int dwFlags, uint dwDesiredAccess, IntPtr lpsa);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool CloseDesktop(IntPtr hDesktop);

    [DllImport("user32.dll")]
    private static extern bool SetThreadDesktop(IntPtr hDesktop);

    [DllImport("kernel32.dll")]
    private static extern uint GetLastError();

    const int DESKTOP_CREATEWINDOW = 0x0002;
    const int DESKTOP_SWITCHDESKTOP = 0x0100;
    const uint GENERIC_ALL = 0x10000000;

    static void Main(string[] args)
    {
        // 创建临时桌面
        IntPtr tempDesktop = CreateDesktop("TempWorkerDesktop", IntPtr.Zero, IntPtr.Zero, 0, GENERIC_ALL, IntPtr.Zero);
        if (tempDesktop == IntPtr.Zero)
        {
            Console.WriteLine($"创建桌面失败,错误码:{GetLastError()}");
            return;
        }

        // 将当前线程切换到临时桌面
        if (!SetThreadDesktop(tempDesktop))
        {
            Console.WriteLine($"切换线程桌面失败,错误码:{GetLastError()}");
            CloseDesktop(tempDesktop);
            return;
        }

        Process process = new Process();
        ProcessStartInfo startInfo = new ProcessStartInfo()
        {
            FileName = @"D:\PathTo\WorkerProcess.exe",
            Arguments = "-misc parameters",
            RedirectStandardOutput = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };
        process.StartInfo = startInfo;
        process.Start();
        process.WaitForExit(10000);
        string processConsoleOutput = process.StandardOutput.ReadToEnd();
        process.Close();

        // 切回原桌面并销毁临时桌面
        SetThreadDesktop(IntPtr.Zero);
        CloseDesktop(tempDesktop);

        Console.WriteLine("Press Enter to exit.");
        Console.ReadLine();
    }
}

方案3:拦截全局键盘事件(兜底方案)

如果前两种方法都无效,可以在主进程中挂载全局键盘钩子,识别并忽略子进程触发的回车键。这个方法复杂度较高,且可能影响系统内其他程序的键盘输入,仅作为兜底方案使用:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

class Program
{
    private static IntPtr _hookId = IntPtr.Zero;
    private static int _workerProcessId;

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);

    private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
        {
            int vkCode = Marshal.ReadInt32(lParam);
            if (vkCode == (int)Keys.Return)
            {
                // 获取触发键盘事件的进程ID
                uint processId;
                GetWindowThreadProcessId(GetForegroundWindow(), out processId);
                if (processId == _workerProcessId)
                {
                    // 忽略子进程触发的回车键
                    return (IntPtr)1;
                }
            }
        }
        return CallNextHookEx(_hookId, nCode, wParam, lParam);
    }

    [DllImport("user32.dll")]
    private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();

    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;

    static void Main(string[] args)
    {
        // 设置全局键盘钩子
        _hookId = SetHook(HookCallback);

        Process process = new Process();
        ProcessStartInfo startInfo = new ProcessStartInfo()
        {
            FileName = @"D:\PathTo\WorkerProcess.exe",
            Arguments = "-misc parameters",
            RedirectStandardOutput = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };
        process.StartInfo = startInfo;
        process.Start();
        _workerProcessId = process.Id;
        process.WaitForExit(10000);
        string processConsoleOutput = process.StandardOutput.ReadToEnd();
        process.Close();

        Console.WriteLine("Press Enter to exit.");
        Console.ReadLine();

        // 卸载钩子
        UnhookWindowsHookEx(_hookId);
    }

    private static IntPtr SetHook(LowLevelKeyboardProc proc)
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
            return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
        }
    }
}

内容的提问来源于stack exchange,提问作者Anketam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 11:44:57