Windows C++如何通过PID向运行中进程(如cmd)的STDIN写入命令
通过C++和Windows API向指定PID的CMD进程发送命令
核心原理
要给已运行的CMD进程的STDIN发送命令,核心是附加到目标CMD的控制台会话,通过控制台输入句柄发送命令文本(需包含回车触发执行)。默认CMD的STDIN绑定自身控制台,无法直接通过进程句柄获取,必须借助控制台相关API操作。
实现步骤
- 释放自身控制台(若存在):当前进程若已有控制台,需先调用
FreeConsole()释放,避免附加目标控制台时出错。 - 附加到目标CMD的控制台:使用
AttachConsole()传入目标进程PID,将当前进程绑定到目标CMD的控制台会话。 - 获取控制台输入句柄:通过
GetStdHandle(STD_INPUT_HANDLE)获取对应目标CMD STDIN的句柄。 - 发送命令内容:构造命令字符串+回车符(
\r\n),用WriteFile()写入控制台输入句柄,触发CMD执行命令。 - 清理资源:完成输入后调用
FreeConsole()脱离目标控制台,不影响后续操作。
代码示例
#include <Windows.h> #include <iostream> #include <string> bool SendCommandToCmd(DWORD dwPID, const char* szCommand) { // 释放当前进程的控制台(如果存在) FreeConsole(); // 附加到目标CMD进程的控制台 if (!AttachConsole(dwPID)) { std::cerr << "AttachConsole failed, error code: " << GetLastError() << std::endl; return false; } // 获取控制台输入句柄 HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); if (hStdIn == INVALID_HANDLE_VALUE) { std::cerr << "GetStdHandle failed, error code: " << GetLastError() << std::endl; FreeConsole(); return false; } // 构造完整输入:命令 + 回车(触发CMD执行) std::string fullInput = szCommand; fullInput += "\r\n"; // 写入控制台输入 DWORD bytesWritten = 0; if (!WriteFile(hStdIn, fullInput.c_str(), fullInput.size(), &bytesWritten, nullptr)) { std::cerr << "WriteFile failed, error code: " << GetLastError() << std::endl; FreeConsole(); return false; } // 脱离目标控制台 FreeConsole(); return true; } int main() { DWORD targetPID = 1234; // 替换为你的CMD进程PID const char* command = "echo hello from external program"; // 要执行的命令 if (SendCommandToCmd(targetPID, command)) { std::cout << "Command sent successfully." << std::endl; } else { std::cout << "Failed to send command." << std::endl; } return 0; }
注意事项
- 权限要求:当前进程需具备足够权限附加到目标CMD进程,建议以管理员身份运行程序避免权限不足。
- STDIN重定向情况:若目标CMD进程是通过重定向STDIN启动(比如从文件/管道读取输入),此方法会失效,因为其STDIN未绑定到控制台。
- 编码适配:示例使用ANSI编码,若需处理Unicode命令,可改用
WriteConsoleW()和宽字符字符串。
内容的提问来源于stack exchange,提问作者user23814685
相关产品推荐
相关产品推荐

