c-在Windows上重定向计时器程序的输入和输出时需要帮助



我希望程序能够重定向两者的输入和输出父进程和子进程。例如,

parent "child.exe > child_output.txt" > parent_output.txt

父代呼叫子代。子输出到Child_output,父输出到父输出。

下面的示例代码应该可以工作,但不能。为了方便起见,我将在字符串"ToBeRun"中对子对象的重定向运算符进行硬编码,而不是像在主程序中那样将其作为参数传递。

如果在命令行中没有将任何参数传递给父级,则子级输出将正确重定向到child_output.txt。但是,如果您在命令行上重定向父级的参数,例如通过调用parent.exe>parent_output.txt,则不会重定向父级输出。parent_output.txt已创建,但在程序完成时为空。

#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);
}

我回答了自己的问题:简单地说,WriteConsole()在写入重定向文件时失败。

因此,在写入重定向文件时,需要使用名称恰当的WriteFile()。

正如Harry Johnston所指出的那样,WriteFile()既适用于重定向输出,也适用于常规控制台输出,因此您可以将其用于这两种情况。我就是这么做的。

或者,特别是当您使用Unicode时,您可以接受MSDN的建议,通过调用GetConsoleMode来检查HANDLE是文件句柄还是控制台句柄。如果GetConsoleMode返回0,则它不是控制台。

你为什么要这么做?与WriteFile不同,WriteConsole是一个可以变成unicode或ASCII函数的宏,具体取决于是否定义了unicode。

来自MSDN:

ReadFile和WriteFile函数,或ReadConsole和WriteConsole函数,使应用程序能够读取控制台输入和写入控制台作为字符流输出。ReadConsole和WriteConsole的行为与ReadFile和WriteFile完全相同,只是它们可以用作宽字符函数(其中文本参数必须使用Unicode)或ANSI函数(其中文本参数必须使用>Windows字符集中的字符)。需要维护单个支持Unicode或ANSI字符集的源应使用ReadConsole和WriteConsole。

最新更新