简体   繁体   English

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

[英]How to send wstring buffer to stdin of a child process?

I'm having trouble writing a WString to the STDIN of a child process. 我在将WString写入子进程的STDIN时遇到麻烦。 If I have only acii character string (eg: @WSX3edc), the code works fine, but if it contains a non ascii character (eg: @WSX3edcß) it fails. 如果我只有acii字符串(例如:@ WSX3edc),则代码可以正常工作,但是如果它包含非ascii字符(例如:@WSX3edcß),它将失败。

The child process is 7zr.exe (7Zip cmd line version). 子进程是7zr.exe(7Zip cmd行版本)。 The input I'm writing to the STDIN is the password to extract the file. 我正在写到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;
}

The writefile always succeed but some how the file extraction is not successful due to faulty password injecting mechanism. writefile总是成功,但是由于密码注入机制错误,文件提取无法成功。

Createprocess for this looks like : (si object has the STDIN and STDOUT streams set using a CreatePipe earlier) 为此的Createprocess看起来像:(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;
}

Note : 7zr.exe works just fine with this particular password , if we run it on command-line and paste this password. 注意:如果在命令行上运行并粘贴此密码,则使用该特定密码的7zr.exe可以正常工作 The extraction works fine. 提取工作正常。

If the narrow character set doesn't have the relevant password character, you can't use this approach. 如果窄字符集没有相关的密码字符,则不能使用此方法。 Instead find what option 7zr has for specifying the password. 而是找到7zr用于指定密码的选项。 I don't have an executable called 7zr but I do have 7z , and the command 7z | find /i "pass" 我没有名为7zr的可执行文件,但确实有7z ,命令7z | find /i "pass" 7z | find /i "pass" worked nicely. 7z | find /i "pass"效果很好。


In other news: 在其他新闻中:

  • The variable dwBytesToWrite is initialized with one value, only to be reassigned a few lines later, without having been used. 变量dwBytesToWrite用一个值初始化,仅在以后几行重新分配,而没有使用。

  • goto Cleanup is generally ungood in C++. goto Cleanup在C ++中, goto Cleanup通常是不好的。 If you want guaranteed cleanup use a destructor (the technique called RAII, read up on it). 如果要保证清除,请使用析构函数(称为RAII的技术,请继续阅读)。

  • Microsoft's Hungarian notation, with prefixes such as sz and dw , is generally an abomination. 微软的匈牙利符号,带有szdw前缀,通常是可憎的。 It once, in the 1980's, supported the help system in Microsoft's Programmer's Workbench. 在1980年代,它曾经在Microsoft的Programmer's Workbench中支持帮助系统。 AFAIK that product hasn't existed the last 30 years or so. AFAIK该产品在过去30年左右不存在。

  • The C cast in (LPWSTR)cmd can easily introduce a bug. (LPWSTR)cmd(LPWSTR)cmd的C很容易引入错误。 Use const_cast where you want to cast constness. 在要const_cast地方使用const_cast Then it would be more clear that this cast is incorrect: you need a mutable buffer. 然后,更清楚的是此强制转换是不正确的:您需要一个可变的缓冲区。

  • Instead of reporting a failure to the standard output stream, via std::cout , consider using the standard error stream, via either std::cerr or std::clog . 可以通过std::cerrstd::clog使用标准错误流,而不是通过std::cout向标准输出流报告故障。 Better, don't do i/o at the place where a failure is detected, but throw an exception to let the calling code deal with it. 更好的是,不要在检测到故障的地方进行I / O操作,而要抛出异常以使调用代码进行处理。 The calling code can't remove output that's already, uh, output. 调用代码无法删除已经输出的输出。

wcslen(wide) returns the number of wide characters in its argument wide ( see ). wcslen(wide)返回其自变量的宽字符wide )。

wcstombs(narrow,wide,len) writes no more than len bytes to narrow ( see ). wcstombs(narrow,wide,len)最多可以写入len 个字节narrow请参阅 len )。

Now if we always had one wide character = one narrow character = one byte, it wouldn't have much sense to have two varieties of characters, would it? 现在,如果我们总是有一个宽字符=一个窄字符=一个字节,那么拥有两种字符就没有多大意义了,是吗?

As soon as you have a wide character that translates to more than one narrow character, there is undefined behaviour. 一旦将宽字符转换为多个窄字符,就会出现不确定的行为。

Since your szBuffer is of fixed size, you could just as well write 由于您的szBuffer具有固定大小,因此您可以编写

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM