2つのアプリがあります。CreateProcessとリダイレクト出力
AppCMD
はコマンドラインアプリケーションであり、AppMAIN
はコマンドライン引数であるAppCMD
を起動します。 残念ながらAppMAIN
は出力を処理していないようですAppCMD
非常にうまくいくものがあります。
AppCMD
とその出力を呼び出して、何が起こっているのかを確認したいと思います。
AppCMD
を別のバイナリAppWRAP
に置き換えて、名前を変更したAppCMD
への転送を転送し、その出力をログに記録します。 AppWRAP
は透明なMan-In-The-Middleのように行動する必要があります。テスト目的のために
私はちょうどそれのコマンドライン引数を出力する簡単なAppCMD
を書いた:
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
cout << "#### Hello, I'm the test binary that wants to be wrapped." << endl;
if (argc < 2) {
cout << "#### There where no command line arguments." << endl;
}
else {
cout << "#### These are my command line arguments:";
for (int i = 1; i < argc; ++i) cout << " " << argv[i];
cout << endl;
}
cout << "#### That's pretty much everything I do ... yet ;)" << endl;
return 0;
}
私はAppWrap
を実装するためにMSDN: Creating a Child Process with Redirected Input and Outputを追ったが、それは返さないと、私はその理由を把握カント以来、私は捕まってしまった:
#include <iostream>
#include <sstream>
#include <Windows.h>
using namespace std;
const string TARGET_BINARY("TestBinary.exe");
const size_t BUFFSIZE = 4096;
HANDLE in_read = 0;
HANDLE in_write = 0;
HANDLE out_read = 0;
HANDLE out_write = 0;
int main(int argc, char *argv[])
{
stringstream call;
cout << "Hello, I'm BinTheMiddle." << endl;
//-------------------------- CREATE COMMAND LINE CALL --------------------------
call << TARGET_BINARY;
for (int i = 1; i < argc; ++i) {
call << " " << argv[i];
}
cout << "Attempting to call '" << call.str() << "'" << endl;
//------------------------------ ARRANGE IO PIPES ------------------------------
SECURITY_ATTRIBUTES security;
security.nLength = sizeof(SECURITY_ATTRIBUTES);
security.bInheritHandle = NULL;
security.bInheritHandle = TRUE;
security.lpSecurityDescriptor = NULL;
if (!CreatePipe(&out_read, &out_write, &security, 0)) {
cout << "Error: StdoutRd CreatePipe" << endl;
return -1;
}
if (!SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)) {
cout << "Stdout SetHandleInformation" << endl;
return -2;
}
if (!CreatePipe(&in_read, &in_write, &security, 0)) {
cout << "Stdin CreatePipe" << endl;
return -3;
}
if (!SetHandleInformation(in_write, HANDLE_FLAG_INHERIT, 0)) {
cout << "Stdin SetHandleInformation" << endl;
return -4;
}
//------------------------------ START TARGET APP ------------------------------
STARTUPINFO start;
PROCESS_INFORMATION proc;
ZeroMemory(&start, sizeof(start));
start.cb = sizeof(start);
start.hStdError = out_write;
start.hStdOutput = out_write;
start.hStdInput = in_read;
start.dwFlags |= STARTF_USESTDHANDLES;
ZeroMemory(&proc, sizeof(proc));
// Start the child process.
if (!CreateProcess(NULL, (LPSTR) call.str().c_str(), NULL, NULL, TRUE,
0, NULL, NULL, &start, &proc))
{
cout << "CreateProcess failed (" << GetLastError() << ")" << endl;
return -1;
}
// Wait until child process exits.
WaitForSingleObject(proc.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle(proc.hProcess);
CloseHandle(proc.hThread);
//----------------------------------- OUTPUT -----------------------------------
DWORD dwRead;
CHAR chBuf[127];
while (ReadFile(out_read, chBuf, 127, &dwRead, NULL)) {
cout << "Wrapped: " << chBuf << endl;
}
return 0;
}
ReadFile
が復帰するのを待っているようです。誰かが私が間違っていることを発見することはできますか?
私は、バイナリをこのように呼ん:
> shell_cmd_wrapper.exe param1 param2
これは、コンソール出力であるが、バイナリは戻りません。
Hello, I'm BinTheMiddle.
Attempting to call 'TestBinary.exe param1 param2'
Wrapped:#### Hello, I'm the test binary that wants to be wrapped.
#### These are my command line arguments: param1 param2
#### That'sD
Wrapped: pretty much everything I do ... yet ;)
s to be wrapped.
#### These are my command line arguments: param1 param2
#### That'sD
(私はバッファをクリアしていないことを無視してください)
利用可能なデータのサイズを調べるために、読み込む前に 'PeekNamedPipe'を使う必要があるでしょう。 – VTT
@eryksunありがとうございました。私は 'CloseHandle(out_write);と呼んだ。 CloseHandle(in_read); 'そして、それは何をすべきかをしているようです:)私は、あなたがそれを書く計画を持っているときに答えを受け入れる計画を持っています。 – lupz
'ReadFile()'の後ろに、 'ReadFile'がそれをしないので、ヌルターミネータを' chBuf'に追加するべきです。あなたは 'chBuf'が当初ゼロで埋められていたのは幸運かもしれませんが、それはランダムなデータでもよいので、' cout'は実際の文字列の後にゴミを書き込んだり、クラッシュすることさえあります。 – zett42