如何通过Python/C/C++远程控制命令行应用?
解决方案
Python 实现
用subprocess模块直接和目标命令行进程建立管道通信,这是最可靠的方式,完全不需要依赖GUI模拟操作。
示例代码:
import subprocess import threading # 启动目标命令行应用,重定向标准输入输出 proc = subprocess.Popen( ["your_cli_app.exe"], # 替换为你的命令行应用路径 stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, # 将错误输出合并到标准输出统一读取 text=True, # 以文本模式处理,避免字节编码问题 bufsize=1, # 启用行缓冲,实现实时读取输出 universal_newlines=True ) # 持续读取应用输出的函数 def read_output(): while True: line = proc.stdout.readline() # 进程结束且无输出时退出循环 if not line and proc.poll() is not None: break if line: print(f"应用输出: {line.strip()}") # 向应用发送命令的函数 def send_command(cmd): proc.stdin.write(cmd + "\n") proc.stdin.flush() # 强制刷新缓冲区,确保命令立即发送 # 启动读取线程,避免阻塞主线程 threading.Thread(target=read_output, daemon=True).start() # 模拟发送命令 send_command("your_command_here") send_command("another_command") # 等待进程结束(可选,根据需求决定是否保留) proc.wait()
关键说明:
subprocess.Popen直接创建子进程并建立管道,读写标准流的方式比GUI模拟稳定得多text=True和bufsize=1确保按行实时读取输出,避免缓冲区堆积导致的延迟- 用线程处理读取操作,防止主线程被阻塞
C/C++ 实现(Windows平台)
Windows下可通过CreateProcess结合匿名管道实现进程通信,直接重定向目标程序的标准输入输出。
关键代码片段:
#include <windows.h> #include <iostream> #include <thread> HANDLE hChildStdinWr; HANDLE hChildStdoutRd; // 创建管道并启动子进程 bool StartChildProcess(const char* cmdPath) { SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; // 创建标准输出管道 HANDLE hChildStdoutWr; if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) return false; SetHandleInformation(hChildStdoutRd, HANDLE_FLAG_INHERIT, 0); // 创建标准输入管道 HANDLE hChildStdinRd; if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) return false; SetHandleInformation(hChildStdinWr, HANDLE_FLAG_INHERIT, 0); STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.hStdError = hChildStdoutWr; si.hStdOutput = hChildStdoutWr; si.hStdInput = hChildStdinRd; si.dwFlags |= STARTF_USESTDHANDLES; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); if (!CreateProcess(NULL, (LPSTR)cmdPath, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { // 清理句柄 CloseHandle(hChildStdinRd); CloseHandle(hChildStdinWr); CloseHandle(hChildStdoutRd); CloseHandle(hChildStdoutWr); return false; } // 关闭不需要的句柄 CloseHandle(pi.hProcess); CloseHandle(pi.hThread); CloseHandle(hChildStdinRd); CloseHandle(hChildStdoutWr); return true; } // 读取子进程输出 void ReadOutput() { char buffer[4096]; DWORD bytesRead; while (ReadFile(hChildStdoutRd, buffer, sizeof(buffer)-1, &bytesRead, NULL) && bytesRead > 0) { buffer[bytesRead] = '\0'; std::cout << "应用输出: " << buffer; } } // 发送命令到子进程 void SendCommand(const char* cmd) { DWORD bytesWritten; WriteFile(hChildStdinWr, cmd, strlen(cmd), &bytesWritten, NULL); // 发送换行符(多数命令行应用需要回车触发命令执行) WriteFile(hChildStdinWr, "\n", 1, &bytesWritten, NULL); } int main() { if (!StartChildProcess("your_cli_app.exe")) { std::cerr << "启动子进程失败" << std::endl; return 1; } // 启动读取线程 std::thread readThread(ReadOutput); readThread.detach(); // 发送测试命令 SendCommand("your_command_here"); SendCommand("another_command"); // 等待用户输入,避免程序提前退出 std::cin.get(); return 0; }
关键说明:
- 通过
STARTUPINFO将子进程的标准输入输出重定向到匿名管道 - 用
ReadFile和WriteFile直接操作管道句柄,实现稳定的读写交互 - 注意及时关闭无用句柄,避免系统资源泄漏
为什么pyautogui不适合
pyautogui是通过模拟鼠标键盘操作控制GUI窗口,针对CMD场景存在明显缺陷:
- 只能读取窗口缓冲区文本(需额外复杂处理),无法直接获取进程的标准输出
- 模拟输入受窗口焦点、光标位置影响极大,稳定性差
- 无法区分目标进程输出和其他窗口内容,可靠性远不如直接操作进程流
内容的提问来源于stack exchange,提问作者Patrik Bede
相关产品推荐
相关产品推荐

