I would like the program to be able to redirect input and output for both parent and child processes. For example,
parent "child.exe > child_output.txt" > parent_output.txt
Parent calls child. Child outputs to child_output, parent outputs to parent output.
The below example code should work, but doesn't. For convenience, I'm hard coding the child's redirection operator in the string "ToBeRun", rather than passing it as an argument, as will be done in the main program.
If no arguments are passed to the parent at the command line, the child output is properly redirected to child_output.txt. But, if you redirect the parent's argument on the command line, say by calling parent.exe > parent_output.txt, the parent output is not redirected. parent_output.txt is created, but is empty at program completion.
#include <windows.h>
// COPY PASTED FROM Martins Mozeiko on Handmade Network:
// https://hero.handmade.network/forums/code-discussion/t/94
// these shouldn't have to be in here, but hey! What can you do?
#pragma function(memset)
void *memset(void *dest, int c, size_t count)
{
char *bytes = (char *)dest;
while (count--)
{
*bytes++ = (char)c;
}
return dest;
}
#pragma function(memcpy)
void *memcpy(void *dest, void *src, size_t count)
{
char *dest8 = (char *)dest;
char *src8 = (char *)src;
while (count--)
{
*dest8++ = *src8++;
}
return dest;
}
/* Based on this msdn article
* https://msdn.microsoft.com/en-us/library/windows/desktop /ms682512(v=vs.85).aspx
*/
int main(void)
{
// init structures for child process
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// start child process and wait for it to finish
#if 0
char *ToBeRun = "/C child.exe > child_result.txt";
#else
// for your convenience, so you don't have to compile a sample child.exe
char *ToBeRun = "/C dir > child_result.txt";
#endif
if( !CreateProcess("C:\\WINDOWS\\system32\\cmd.exe", // Module name
ToBeRun, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
// create process failed
return 1;
}
WaitForSingleObject(pi.hProcess, INFINITE);
// print parent output string
char String[] = "This is the parent's output";
int StringLength = sizeof(String) / sizeof(String[0]);
DWORD CharsWritten;
HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE);
WriteConsole(Handle, String, StringLength, &CharsWritten, NULL);
// close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
return 0;
}
// required for compiling without CRT
void mainCRTStartup(void)
{
int Result = main();
ExitProcess(Result);
}