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

如何通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 11:05:26