C#中如何向已启动运行的EXE程序传入参数?
嘿,我来帮你理清这个问题——你之前用的Process.StartInfo.Arguments其实只能在启动程序的时候传递命令行参数,完全没法给已经跑起来的进程发新参数哦!要给运行中的EXE传参,得用进程间通信(IPC)的办法,我给你整理几种实用的方案:
1. 给GUI程序发Windows消息
如果你的目标EXE是带界面的GUI程序,发送自定义Windows消息是个靠谱的思路:
- 先找到目标进程的主窗口句柄(可以用
Process.MainWindowHandle,或者通过窗口标题去搜) - 调用Windows API
SendMessage,把参数打包成消息的附加数据发过去
举个C#的例子:
using System; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; class Program { [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); // 自定义消息ID(得避开系统自带的消息,随便选个不冲突的就行) private const uint WM_MY_PARAM = 0x0400 + 100; static void Main() { // 找到目标进程(这里假设进程名是cmbs_tcx.exe) var targetProcess = Process.GetProcessesByName("cmbs_tcx").FirstOrDefault(); if (targetProcess != null && targetProcess.MainWindowHandle != IntPtr.Zero) { // 把要传的参数转成可传递的指针 var paramPtr = Marshal.StringToHGlobalAuto("要传递的新参数"); SendMessage(targetProcess.MainWindowHandle, WM_MY_PARAM, IntPtr.Zero, paramPtr); Marshal.FreeHGlobal(paramPtr); } } }
⚠️ 注意:这种方法要求目标程序有对应的消息处理逻辑,能接收到你发的消息并解析参数。如果是第三方程序,你可能得确认它支持这种方式,或者通过逆向找到它能响应的消息。
2. 给控制台程序用标准输入传参
如果目标程序是控制台程序,而且支持从标准输入读取内容,那你可以直接通过Process.StandardInput给它发参数:
不过要注意,启动进程的时候得改几个设置——UseShellExecute要设为false,还要开启RedirectStandardInput,不然拿不到输入流。比如你可以把启动代码改成这样:
var P1 = new Process(); P1.StartInfo.WorkingDirectory = @"D:\try"; P1.StartInfo.FileName = "cmbs_tcx.exe"; // 直接启动EXE,不用绕CMD P1.StartInfo.Arguments = "-han"; // 启动时的初始参数 P1.StartInfo.UseShellExecute = false; P1.StartInfo.CreateNoWindow = true; P1.StartInfo.RedirectStandardInput = true; // 必须开启这个才能用StandardInput P1.Start(); // 等程序跑起来后,动态传参 P1.StandardInput.WriteLine("你的新参数内容"); P1.StandardInput.Flush();
3. 通用方案:命名管道或套接字
如果上面两种方法都不适用,命名管道或者TCP/UDP套接字是更通用的选择。这种方式的好处是不管目标程序是GUI还是控制台都能用,但前提是目标程序得支持对应的通信协议,或者你能修改目标程序的代码来实现接收逻辑。
举个命名管道的简单例子:
- 发送参数的客户端代码:
using System.IO.Pipes; using System.IO; class PipeClient { static void Main() { using (var pipeClient = new NamedPipeClientStream(".", "MyCustomPipe", PipeDirection.Out)) { pipeClient.Connect(); using (var sw = new StreamWriter(pipeClient)) { sw.WriteLine("要传递的参数"); sw.Flush(); } } } }
- 接收参数的目标程序(服务端)代码:
using System.IO.Pipes; using System.IO; class PipeServer { static void Main() { using (var pipeServer = new NamedPipeServerStream("MyCustomPipe", PipeDirection.In)) { pipeServer.WaitForConnection(); using (var sr = new StreamReader(pipeServer)) { var receivedParam = sr.ReadLine(); // 这里写处理参数的逻辑 Console.WriteLine($"收到新参数:{receivedParam}"); } } } }
对你现有代码的小建议
你之前通过CMD来启动EXE,还用到了&(应该是&的转义?),其实如果只是启动时传参数,直接启动EXE会更靠谱,参数传递也不容易出问题。另外UseShellExecute = true的时候,系统shell会处理参数,有时候可能会有解析错误,改成UseShellExecute = false能让参数传递更稳定。
内容的提问来源于stack exchange,提问作者Sasha777

