C++提取CMD命令输出中变动的端口号与Remoting Auth Token
解决C++提取LeagueClientUx端口与remoting-auth-token的问题
我来帮你搞定这个问题!要提取目标进程的端口和token,得分成两步走:先正确捕获WMIC命令的输出,再用正则精准匹配需要的内容。
第一步:捕获WMIC命令的输出到std::string
直接用system()调用CMD命令没法获取输出,得用Windows的管道机制来捕获标准输出。下面是封装好的函数,能把指定命令的输出转换成std::string:
#include <windows.h> #include <string> #include <iostream> std::string executeCommand(const std::string& cmd) { std::string result; HANDLE hReadPipe, hWritePipe; SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE}; if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) { return ""; } STARTUPINFO si = {sizeof(STARTUPINFO)}; si.hStdOutput = hWritePipe; si.hStdError = hWritePipe; si.dwFlags |= STARTF_USESTDHANDLES; PROCESS_INFORMATION pi; if (!CreateProcess(nullptr, const_cast<char*>(cmd.c_str()), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &pi)) { CloseHandle(hReadPipe); CloseHandle(hWritePipe); return ""; } CloseHandle(hWritePipe); char buffer[4096]; DWORD bytesRead; while (ReadFile(hReadPipe, buffer, sizeof(buffer)-1, &bytesRead, nullptr) && bytesRead > 0) { buffer[bytesRead] = '\0'; result += buffer; } CloseHandle(hReadPipe); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return result; }
调用这个函数的时候,直接传你的WMIC命令就行:
std::string cmdOutput = executeCommand("wmic PROCESS WHERE name='LeagueClientUx.exe' GET commandline");
第二步:用正则表达式提取端口和token
WMIC的输出可能会有多余的换行、空格,所以先处理一下(比如去掉重复空白字符),然后用正则匹配--app-port=和--remoting-auth-token=后面的内容。这里用C++11及以上的<regex>库:
#include <regex> #include <algorithm> // 辅助函数:清理多余的空白字符 std::string cleanWhitespace(const std::string& input) { std::string result; bool inWhitespace = false; for (char c : input) { if (std::isspace(static_cast<unsigned char>(c))) { if (!inWhitespace) { result += ' '; inWhitespace = true; } } else { result += c; inWhitespace = false; } } return result; } // 提取端口和token的函数 void extractLeagueClientInfo(const std::string& cmdOutput, std::string& port, std::string& token) { std::string cleaned = cleanWhitespace(cmdOutput); // 匹配端口:--app-port=数字 std::regex portRegex(R"(--app-port=(\d+))"); std::smatch portMatch; if (std::regex_search(cleaned, portMatch, portRegex)) { port = portMatch[1].str(); } // 匹配token:--remoting-auth-token=任意非空白字符(直到下一个参数) std::regex tokenRegex(R"(--remoting-auth-token=(\S+))"); std::smatch tokenMatch; if (std::regex_search(cleaned, tokenMatch, tokenRegex)) { token = tokenMatch[1].str(); } }
完整示例代码
把上面的部分整合起来,就能直接运行:
#include <windows.h> #include <string> #include <iostream> #include <regex> #include <algorithm> std::string executeCommand(const std::string& cmd) { std::string result; HANDLE hReadPipe, hWritePipe; SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE}; if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) { return ""; } STARTUPINFO si = {sizeof(STARTUPINFO)}; si.hStdOutput = hWritePipe; si.hStdError = hWritePipe; si.dwFlags |= STARTF_USESTDHANDLES; PROCESS_INFORMATION pi; if (!CreateProcess(nullptr, const_cast<char*>(cmd.c_str()), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &pi)) { CloseHandle(hReadPipe); CloseHandle(hWritePipe); return ""; } CloseHandle(hWritePipe); char buffer[4096]; DWORD bytesRead; while (ReadFile(hReadPipe, buffer, sizeof(buffer)-1, &bytesRead, nullptr) && bytesRead > 0) { buffer[bytesRead] = '\0'; result += buffer; } CloseHandle(hReadPipe); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return result; } std::string cleanWhitespace(const std::string& input) { std::string result; bool inWhitespace = false; for (char c : input) { if (std::isspace(static_cast<unsigned char>(c))) { if (!inWhitespace) { result += ' '; inWhitespace = true; } } else { result += c; inWhitespace = false; } } return result; } void extractLeagueClientInfo(const std::string& cmdOutput, std::string& port, std::string& token) { std::string cleaned = cleanWhitespace(cmdOutput); std::regex portRegex(R"(--app-port=(\d+))"); std::smatch portMatch; if (std::regex_search(cleaned, portMatch, portRegex)) { port = portMatch[1].str(); } std::regex tokenRegex(R"(--remoting-auth-token=(\S+))"); std::smatch tokenMatch; if (std::regex_search(cleaned, tokenMatch, tokenRegex)) { token = tokenMatch[1].str(); } } int main() { std::string cmdOutput = executeCommand("wmic PROCESS WHERE name='LeagueClientUx.exe' GET commandline"); std::string port, token; extractLeagueClientInfo(cmdOutput, port, token); std::cout << "端口号:" << (port.empty() ? "未找到" : port) << std::endl; std::cout << "Remoting Auth Token:" << (token.empty() ? "未找到" : token) << std::endl; return 0; }
注意事项
- 确保你的项目是用C11或更高版本编译(因为用到了
<regex>和C11的特性) - 如果WMIC输出有多个进程实例(比如开了多个客户端?不过一般不会),正则会匹配第一个找到的,你可以改成循环搜索处理多个实例
- 有时候WMIC的输出开头会有"CommandLine"表头,清理空白后不影响正则匹配,因为正则是找具体的参数项
内容的提问来源于stack exchange,提问作者Lordi1000
相关产品推荐
相关产品推荐

