How do I redirect output to a file with CreateProcess?
Solution 1
You can't use stdout redirection in the command line passed to CreateProcess
. To redirect stdout you need to specify a file handle for the output in the STARTUPINFO
structure.
You are also making another, more subtle, mistake. The second parameter, lpCommandLine
must point to writeable memory because CreateProcess
overwrites the buffer. If you happen to be using the ANSI version of the function then you will get away with this, but not for the Unicode version.
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
Solution 2
The code below creates a console-less process with stdout and stderr redirected to the specified file.
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
HANDLE h = CreateFile(_T("out.log"),
FILE_APPEND_DATA,
FILE_SHARE_WRITE | FILE_SHARE_READ,
&sa,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL );
PROCESS_INFORMATION pi;
STARTUPINFO si;
BOOL ret = FALSE;
DWORD flags = CREATE_NO_WINDOW;
ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) );
ZeroMemory( &si, sizeof(STARTUPINFO) );
si.cb = sizeof(STARTUPINFO);
si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdInput = NULL;
si.hStdError = h;
si.hStdOutput = h;
TCHAR cmd[]= TEXT("Test.exe 30");
ret = CreateProcess(NULL, cmd, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi);
if ( ret )
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
return -1;
}
Solution 3
Microsoft has an example how to redirect the standard output: http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx.
Solution 4
CreateProcess() launches processes, it is not a command line itnerpreter. It doesn't know what ">" is and won't do the stream redirection for you. You need to open the file test.txt yourself and pass the handle to it to CreateProcess inside the STARTUPINFO structure: CreateProcess STARTUPINFO
Related videos on Youtube
Paul Manta
Updated on September 18, 2020Comments
-
Paul Manta over 3 years
I tried using CreateProcess to run a simple command like
hg > test.txt
. I tried running the string as a whole (as opposed to separating it into an application name and its parameters). Why doesCreateProcess(0, "notepad.exe test.txt", ...)
work butCreateProcess(0, "hg > test.txt", ...)
does not?-
cnicutar over 12 years
CreateProcess
doesn't know about redirections. Why don't you usesystem(3)
? Let me guess: you can do it better than system(3). -
Seth Carnegie over 12 years@cnicutar I've always wondered what the
function(number)
notation meant. What doessystem(3)
mean? -
cnicutar over 12 years@Seth Carnegie The manual section.
man 3 system
. -
Veger over 12 years
man 3 system
for Windows?? -
MK. over 12 years@cnicutar he most definitely can do it better than system (on Windows). System will launch cmd.exe and load all kinds of dependencies and cause all kinds of unnecessary things to happen.
-
André Caron over 12 years@cnicutar: Actually,
CreateProcess()
has alpStartupInfo
structure that takes handles to the redirected streams, so it does know about redirections. It just doesn't use the shell notation. -
MK. over 12 years@Seth that's from Unix, you type in man 3 system and it means look up documentation for system in the section 3 of the manual pages (APIs, built-in commands etc)
-
cnicutar over 12 years@MK, André Caron Okay :-) I'm not sure if it's worth it in this case but I'll keep it in mind.
-
-
Frerich Raabe almost 12 yearsHe's not necessarily making a mistake by not making the second parameter point to writeable memory. It's possible that he doesn't compile with
UNICODE
defined, in which caseCreateProcess
isCreateProcessA
, which doesn't have this requirement. -
David Heffernan almost 12 years@FrerichRaabe That's an implementation detail of the current versions of Windows. If you look at the MSDN documentation you will see that the type of the second parameter is
LPTSTR
. In any case, I made the very point that you make in my second paragraph. -
Frerich Raabe almost 12 years@DavidHeffernan: I don't think it's an implementation detail since the documentation you quoted explicitely mentions that the ANSI version does not have this requirement. I'm mostly nitpicking though, because you first wrote "You are also making a mistake" and then you wrote "If you happen to be using the ANSI version". So you don't know if he's doing a mistake, because you don't know whether he's the ANSI version or not.
-
Nux over 11 yearsYeah, that kind of work, but remember there is a bug in that example that prevents
ReadFromPipe
from exiting. Before you call that function you need to call:CloseHandle(g_hChildStd_OUT_Wr);
. Also you'll probably want to wait for the child process to exit before you close the handle to process with something like:WaitForSingleObject(piProcInfo.hProcess, INFINITE);
. -
Mooing Duck over 10 yearsDescription alongside the code would be handy. At least comments
-
SerG almost 10 yearsPossible CloseHandle() of the file after the child process spawned is missed.
-
Delgan over 7 yearsRelated: launch an exe/process with stdin stdout and stderr?. Also, see tiny-process-library which is very convenient.
-
Cristian Amarie about 7 yearsShouldn't hStdInput be INVALID_HANDLE_VALUE instead of NULL?
-
Jeff Wilhite about 5 yearsBy the way, if you use STARTF_USESTDHANDLES and don't want to redirect one of the handles, you can do: si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);