问题根源在于:JSON字符串作为命令行参数传递时,双引号和特殊字符没有正确转义,导致JSON格式被破坏。

 

你的分析完全正确。观察这个调用:

text
"C:\...\BaiduNetdisk.exe" -imgviewimgtopdf "{"actionType":14,"height":1680,...}"

JSON部分 {"actionType":14,...} 虽然外层有双引号包裹,但内部的JSON双引号没有转义。系统会错误地将第一个 " 视为参数结束,导致传递的JSON变成不完整的 {actionType:14,...

🔧 解决方案

方案1:发送方进行转义(推荐)

在构造命令行的发送方,需要对JSON字符串进行转义:

cpp
// 原始JSON字符串
CString strJson = L"{\"actionType\":14,\"height\":1680,...}";

// 转义:将双引号转义为\",反斜杠转义为\\
CString strJsonEscaped = strJson;
strJsonEscaped.Replace(L"\\", L"\\\\");  // 先转义反斜杠
strJsonEscaped.Replace(L"\"", L"\\\"");  // 再转义双引号

// 构造命令
strExe.Format(L"\"%s\" -%s \"%s\"", bsExePath, strCommand, strJsonEscaped);
// 结果:-imgviewimgtopdf "{\"actionType\":14,\"height\":1680,...}"

方案2:接收方进行修复

如果无法修改发送方,可以在接收方尝试修复:

cpp
// 接收方获取参数后,尝试修复常见问题
CString FixJsonString(const CString& strInput)
{
    CString strResult = strInput;
    
    // 情况1:参数可能丢失了外层引号
    if (strResult.GetLength() > 0 && strResult[0] == L'{' && strResult[strResult.GetLength()-1] == L'}')
    {
        // 已经是完整JSON,直接返回
        return strResult;
    }
    
    // 情况2:尝试查找实际的JSON开始和结束
    int nStart = strResult.Find(L'{');
    int nEnd = strResult.ReverseFind(L'}');
    if (nStart >= 0 && nEnd > nStart)
    {
        return strResult.Mid(nStart, nEnd - nStart + 1);
    }
    
    return strResult;
}

// 使用
CString strFixedJson = FixJsonString(bsJsonData);
if (CString(strFixedJson).IsEmpty())
{
    XLogDebug(L"JsonLib::Parse Input String Is Empty");
    return E_FAIL;
}

方案3:使用Base64编码(最可靠)

最彻底的方法是使用Base64编码传递JSON:

发送方:

cpp
// 对JSON进行Base64编码
CStringA strJsonUtf8 = CT2A(strJson, CP_UTF8);
CString strBase64 = Base64Encode(strJsonUtf8);  // 实现Base64编码

// 发送编码后的数据
strExe.Format(L"\"%s\" -%s %s", bsExePath, strCommand, strBase64);

接收方:

cpp
// 解码Base64
CStringA strUtf8Json = Base64Decode(bsJsonData);  // 实现Base64解码
CStringW strJson = CA2W(strUtf8Json, CP_UTF8);

// 继续原有解析流程
CStringA utf8JsonContactData;
AppUtil::Misc::TransformWStringToUtf8String(strJson, utf8JsonContactData);

📋 调试建议

添加详细日志来确定问题:

cpp
// 在解析前输出原始参数
XLogDebug(L"JsonLib::Parse Raw Input: %s", bsJsonData);
XLogDebug(L"JsonLib::Parse Input Length: %d", CString(bsJsonData).GetLength());

// 输出转换后的UTF8字符串
CStringA utf8JsonContactData;
AppUtil::Misc::TransformWStringToUtf8String(bsJsonData, utf8JsonContactData);
XLogDebug(L"JsonLib::Parse UTF8 Length: %d", utf8JsonContactData.GetLength());


核心理解:

1、调式技能 : 同时起来一个exe和另外一个exe时,可以通过 childProcess插件处理;
2、起来命令行的方式,改为我们软件内部的这个output下面的exe,保证模拟一摸一样的启动方式;
3、理解字符串转义是Windows系统编程和跨进程通信中的重要基础。在调试时,可以添加日志来验证每个阶段的字符串内容,这会帮助你更直观地理解转义过程。

(1)一定要理解 在c++中书写的代码(字面量写法),和实际代表(实际内存含义)的含义这两个层面。
(2)顺序要求 : 核心最先把里带有转移字符的给替换,后面给特殊字符再增加一个转义字符,避免多增加一份转义字符的问题;

🎯 核心要点总结

  1. C++编译器的转义:在代码中写"\\"会创建一个包含单个\的字符串

  2. Windows命令行的转义:命令行解析器也需要转义字符来识别特殊字符

  3. 双重转义的必要性

    • 第一层:为了JSON格式本身(JSON中的\

    • 第二层:为了命令行解析(不被命令行误解析)

  4. 转义顺序很重要:先转义\,再转义",否则会出错

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。