如何将wstring缓冲区发送到子进程的stdin?

时间:2017-01-12 06:36:09

标签: c++ named-pipes

我在将WString写入子进程的STDIN时遇到问题。如果我只有acii字符串(例如:@ WSX3edc),代码工作正常,但如果它包含非ascii字符(例如:@WSX3edcß)则失败。

子进程是7zr.exe(7Zip cmd行版本)。我写给STDIN的输入是提取文件的密码。

// inject password
wPassword.append(password);
wPassword.append(L"\n"); \\For carriage return
...
DWORD dwBytesToWrite = wPassword.length()*sizeof(wchar_t);
DWORD dwBytesWritten = 0;
char szBuffer[1024] = "\0";
wcstombs(szBuffer, wPassword.c_str(),wcslen(wPassword.c_str())+1);
dwBytesToWrite = strlen(szBuffer);
if (!WriteFile(hInput, szBuffer, dwBytesToWrite, &dwBytesWritten, NULL)) {
    std::cout<<"write file failed"<<GetLastError()<<std::endl;
    goto Cleanup;
}

写文件总是成功但是由于密码注入机制错误导致文件提取不成功。

Createprocess for this貌似如下:(si对象具有先前使用CreatePipe设置的STDIN和STDOUT流)

if(!CreateProcess((LPWSTR)cmd, (LPWSTR)cmdArgs, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS,
        NULL, NULL, &si, &pi)) {
         std::cout<<"7zr.exe process creation failed "<<GetLastError()<<std::endl;
         goto Cleanup;
}

注意: 7zr.exe可以正常使用此特定密码,如果我们在命令行运行它并粘贴此密码。提取工作正常。

2 个答案:

答案 0 :(得分:2)

如果窄字符集没有相关的密码字符,则无法使用此方法。而是找到7zr用于指定密码的选项。我没有名为7zr的可执行文件,但我确实有7z,命令7z | find /i "pass"效果很好。

在其他新闻中:

  • 变量dwBytesToWrite初始化为一个值,只是稍后重新分配几行而未被使用。

  • goto Cleanup通常在C ++中是不合适的。如果你想保证清理使用析构函数(称为RAII的技术,请阅读它)。

  • 微软的匈牙利表示法,带有szdw等前缀,通常是令人厌恶的。它曾经在1980年代支持微软程序员工作台中的帮助系统。 AFAIK产品在过去30年左右不存在。

  • (LPWSTR)cmd中的C演员很容易引入错误。使用const_cast来编译constness。然后更清楚的是,这个演员是不正确的:你需要一个可变的缓冲区。

  • 不是通过std::cout向标准输出流报告失败,而是考虑通过std::cerrstd::clog使用标准错误流。更好,不要在检测到故障的地方进行i / o,但抛出异常让调用代码处理它。调用代码无法删除已经输出的输出。

答案 1 :(得分:1)

wcslen(wide)在其参数widesee)中返回宽字符的数量。

wcstombs(narrow,wide,len)lensee)写入的narrow 字节不超过

现在,如果我们总是有一个宽字符=一个窄字符=一个字节,那么拥有两种字符就没有多大意义了,不是吗?

只要你有一个宽字符转换为多个窄字符,就会有不确定的行为。

由于szBuffer的大小固定,您也可以写

wcstombs(szBuffer, wPassword.c_str(), sizeof(szBuffer));