linux下需以二进制模式读取/proc/self/cmdline并按空字符\0切分参数,windows则调用getcommandlinew获取宽字符串后转utf-8;两者均不可用普通文本读取或getmodulefilename替代。

Linux下读取/proc/self/cmdline需要逐字节解析空字符分隔
Linux内核把原始命令行参数以\0(空字符)拼接后存放在/proc/self/cmdline中,不是普通文本文件——它没有换行,多个参数之间用单个\0隔开,末尾还有一个\0。直接用fgets或std::getline会读到第一个参数就停住。
- 用
std::ifstream以std::ios::binary模式打开,再用read一次性读取全部内容 - 遍历字节数组,遇到
\0就切分出一个参数;连续\0不会出现,所以每段非空字节即为一个参数 - 注意:
/proc/self/cmdline可能被进程自己或特权进程修改,但通常可靠;若文件不可读(如容器限制),需降级处理
std::string read_cmdline() {
std::ifstream f("/proc/self/cmdline", std::ios::binary);
if (!f.is_open()) return "";
std::vector<char> buf((std::istreambuf_iterator<char>(f)), {});
std::string result;
for (size_t i = 0; i i) {
if (!result.empty()) result += " ";
result += std::string(&buf[i], &buf[j]);
}
i = j + 1;
}
return result;
}</char></char>
Windows用GetCommandLineW获取宽字符串再转UTF-8
Windows不提供类似/proc的接口,必须调用GetCommandLineW——它返回的是带引号、空格转义后的原始命令行宽字符串(wchar_t*),和用户启动时输入的几乎一致(包括多余空格、内部引号等)。
- 不能用
GetModuleFileName代替,它只返回可执行路径,不含参数 -
GetCommandLineA在非Unicode系统上不可靠,一律用GetCommandLineW+WideCharToMultiByte - 注意:如果程序是通过
CreateProcess以CREATE_NO_WINDOW等方式启动,该API仍有效;但DLL注入场景下可能指向宿主进程命令行
#include <windows.h>
#include <string>
std::string get_cmdline_utf8() {
wchar_t* wcmd = GetCommandLineW();
if (!wcmd) return "";
int len = WideCharToMultiByte(CP_UTF8, 0, wcmd, -1, nullptr, 0, nullptr, nullptr);
if (len <h3>macOS需组合<code>_NSGetArgc</code>和<code>_NSGetArgv</code>再拼接</h3>
<p>macOS没有<code>/proc</code>,也没有直接等价于<code>GetCommandLineW</code>的API。标准做法是调用<code>_NSGetArgc</code>/<code>_NSGetArgv</code>拿到<code>argv</code>数组,然后手动按规则拼回原始字符串——但这无法还原引号、反斜杠转义等shell层面的处理,只能得到“运行时解析后的参数”。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master"><img
src="https://img.php.cn/upload/skill/000/000/081/179051228971575.jpg" alt="C++ Code Review Master" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="overflowclass">C++ Code Review Master</a>
<p class="overflowclass">组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。</p>
</div>
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<ul>
<li>严格来说,macOS无法获取真正的“启动命令行原始字符串”,因为shell在exec前已做词法解析,内核只接收干净的<code>argv</code>
</li>
<li>若要逼近原始效果,可用<code>NSString *cmd = [[NSProcessInfo processInfo] environment][@"CMDLINE"]</code>(需启动时由父进程显式注入,非常规)</li>
<li>多数情况下,拼接<code>argv[0]</code>到<code>argv[argc-1]</code>并用空格分隔已够用,但要注意参数本身含空格时会被破坏</li>
</ul>
<h3>跨平台封装时别忽略<code>argv[0]</code>可能被篡改</h3>
<p>无论哪个平台,<code>argv[0]</code>(程序名部分)在启动后都可能被代码主动修改(例如<code>prctl(PR_SET_NAME)</code>或直接写<code>argv[0][0] = 0</code>),而<code>/proc/self/cmdline</code>或<code>GetCommandLineW</code>返回的是初始值——二者可能不一致。</p>
<ul>
<li>如果你关心“刚启动时用户敲了什么”,就信<code>/proc/self/cmdline</code>或<code>GetCommandLineW</code>
</li>
<li>如果你关心“当前进程自称什么”,就看<code>argv[0]</code>(但注意它可能已被改写)</li>
<li>第三方库如<code>boost::program_options</code>或<code>absl::flags</code>只解析<code>argv</code>,不碰原始命令行,这点要分清</li>
</ul>
<p>真正难的不是读取,而是定义清楚“原始字符串”到底指哪一层:shell输入?execve传入?还是内核保存的副本?不同场景答案不同。</p></string></windows.h>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










