我在将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可以正常使用此特定密码,如果我们在命令行运行它并粘贴此密码。提取工作正常。
答案 0 :(得分:2)
如果窄字符集没有相关的密码字符,则无法使用此方法。而是找到7zr
用于指定密码的选项。我没有名为7zr
的可执行文件,但我确实有7z
,命令7z | find /i "pass"
效果很好。
在其他新闻中:
变量dwBytesToWrite
初始化为一个值,只是稍后重新分配几行而未被使用。
goto Cleanup
通常在C ++中是不合适的。如果你想保证清理使用析构函数(称为RAII的技术,请阅读它)。
微软的匈牙利表示法,带有sz
和dw
等前缀,通常是令人厌恶的。它曾经在1980年代支持微软程序员工作台中的帮助系统。 AFAIK产品在过去30年左右不存在。
(LPWSTR)cmd
中的C演员很容易引入错误。使用const_cast
来编译constness。然后更清楚的是,这个演员是不正确的:你需要一个可变的缓冲区。
不是通过std::cout
向标准输出流报告失败,而是考虑通过std::cerr
或std::clog
使用标准错误流。更好,不要在检测到故障的地方进行i / o,但抛出异常让调用代码处理它。调用代码无法删除已经输出的输出。
答案 1 :(得分:1)