When I run an exe file through a bat file as intermediary for stdin and stdout pipes then it works, but not when I run it directly
I have an exe file: p.exe. It is supposed to receive input on stdin and then output on stdout. If I run it manually and input: "hello" then it responds "help".
If I run it through createProcessA and give it "hello\n" through WriteFile, then I can see it working (processmonitor), but I do not get any output on stdOut or stdErr.
Therefore, I created a batscript as intermediary:
@echo off
setlocal
:input_loop
set /p UserInput=
:: Check if the input is 'exit' to break the loop
if "%UserInput%"=="exit" goto end_loop
:: Pass the input to p.exe and display the output
echo %UserInput% | %~dp0p.exe
:: Go back to the start of the loop
goto input_loop
:end_loop
endlocal
and then I can run this batscript through createProcessA, and it works!
Here is my test:
TEST_METHOD(SO_TEST) {
std::string path = "test.bat";
HANDLE hStdInPipeWrite;
HANDLE hStdOutPipeRead;
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
HANDLE hStdInPipeRead = NULL;
HANDLE hStdOutPipeWrite = NULL;
// Create two pipes
//hStdInPipeRead is the read end of the pipe for the child process. hstdinPipeWrite is the write end of the pipe for the parent process.
//hstdoutPipeRead is the read end of the pipe for the parent process. hstdoutPipeWrite is the write end of the pipe for the child process.
if (!CreatePipe(&hStdInPipeRead, &hStdInPipeWrite, &sa, 0) ||
!CreatePipe(&hStdOutPipeRead, &hStdOutPipeWrite, &sa, 0)) {
abort();
}
SetHandleInformation(hStdInPipeWrite, HANDLE_FLAG_INHERIT, 0);
SetHandleInformation(hStdOutPipeRead, HANDLE_FLAG_INHERIT, 0);
STARTUPINFOA si = {};
si.cb = sizeof(STARTUPINFO);
si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdError = hStdOutPipeWrite;
si.hStdOutput = hStdOutPipeWrite;
si.hStdInput = hStdInPipeRead;
std::string directory = path.substr(0, path.find_last_of("\\"));
std::string fileName = path.substr(path.find_last_of("/\\") + 1);
PROCESS_INFORMATION pi = {};
if (!CreateProcessA(NULL, const_cast<char*>(path.c_str()), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
DWORD lastError = GetLastError();
abort();
}
// Close pipes as they belong to the child
CloseHandle(hStdOutPipeWrite);
CloseHandle(hStdInPipeRead);
std::string data = "hello";
DWORD dwWritten;
bool result = WriteFile(hStdInPipeWrite, data.c_str(), data.length(), &dwWritten, NULL);
char buf[1024 + 1];
DWORD dwRead;
if (ReadFile(hStdOutPipeRead, buf, 1024, &dwRead, NULL)) {
buf[dwRead] = '\0';
}
//buf contains "help\r\n"
}
but if I change test.bat to p.exe, then I do not get any output.
I have also tried using https://gitlab.com/eidheim/tiny-process-library with the same result.
I am guessing that it has something to do with the environment, but I do not know what.