QProcess/Win: direct forwarding of stdout and stderr
We are now directly passing the standard out/err handles to CreateProcess instead of reading the output and writing it. The downside is, that we cannot automatically forward the process output of GUI applications anymore. This behaviour is intended by the CreateProcess API. Change-Id: Ic6e35c8c338dbea1a9f345567a37d938da1f34a2 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com> Reviewed-by: Joerg Bornemann <joerg.bornemann@nokia.com>
This commit is contained in:
parent
ece75a8adf
commit
2588a5b249
4
dist/changes-5.0.0
vendored
4
dist/changes-5.0.0
vendored
@ -144,6 +144,10 @@ information about a particular change.
|
|||||||
- The QHttp, QHttpHeader, QHttpResponseHeader and QHttpRequestHeader classes have
|
- The QHttp, QHttpHeader, QHttpResponseHeader and QHttpRequestHeader classes have
|
||||||
been removed, QNetworkAccessManager should be used instead.
|
been removed, QNetworkAccessManager should be used instead.
|
||||||
|
|
||||||
|
- QProcess
|
||||||
|
|
||||||
|
* On Windows, QProcess::ForwardedChannels will not forward the output of GUI
|
||||||
|
applications anymore, if they do not create a console.
|
||||||
|
|
||||||
****************************************************************************
|
****************************************************************************
|
||||||
* General *
|
* General *
|
||||||
|
@ -617,6 +617,14 @@ void QProcessPrivate::Channel::clear()
|
|||||||
writes to its standard output and standard error will be written
|
writes to its standard output and standard error will be written
|
||||||
to the standard output and standard error of the main process.
|
to the standard output and standard error of the main process.
|
||||||
|
|
||||||
|
\note Windows intentionally suppresses output from GUI-only
|
||||||
|
applications to inherited consoles.
|
||||||
|
This does \e not apply to output redirected to files or pipes.
|
||||||
|
To forward the output of GUI-only applications on the console
|
||||||
|
nonetheless, you must use SeparateChannels and do the forwarding
|
||||||
|
yourself by reading the output and writing it to the appropriate
|
||||||
|
output channels.
|
||||||
|
|
||||||
\sa setProcessChannelMode()
|
\sa setProcessChannelMode()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -92,6 +92,15 @@ static void qt_create_pipe(Q_PIPE *pipe, bool in)
|
|||||||
CloseHandle(tmpHandle);
|
CloseHandle(tmpHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void duplicateStdWriteChannel(Q_PIPE *pipe, DWORD nStdHandle)
|
||||||
|
{
|
||||||
|
pipe[0] = INVALID_Q_PIPE;
|
||||||
|
HANDLE hStdWriteChannel = GetStdHandle(nStdHandle);
|
||||||
|
HANDLE hCurrentProcess = GetCurrentProcess();
|
||||||
|
DuplicateHandle(hCurrentProcess, hStdWriteChannel, hCurrentProcess,
|
||||||
|
&pipe[1], 0, TRUE, DUPLICATE_SAME_ACCESS);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create the pipes to a QProcessPrivate::Channel.
|
Create the pipes to a QProcessPrivate::Channel.
|
||||||
|
|
||||||
@ -108,8 +117,11 @@ bool QProcessPrivate::createChannel(Channel &channel)
|
|||||||
|
|
||||||
if (channel.type == Channel::Normal) {
|
if (channel.type == Channel::Normal) {
|
||||||
// we're piping this channel to our own process
|
// we're piping this channel to our own process
|
||||||
qt_create_pipe(channel.pipe, &channel == &stdinChannel);
|
const bool isStdInChannel = (&channel == &stdinChannel);
|
||||||
|
if (isStdInChannel || processChannelMode != QProcess::ForwardedChannels)
|
||||||
|
qt_create_pipe(channel.pipe, isStdInChannel);
|
||||||
|
else
|
||||||
|
duplicateStdWriteChannel(channel.pipe, (&channel == &stdoutChannel) ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
|
||||||
return true;
|
return true;
|
||||||
} else if (channel.type == Channel::Redirect) {
|
} else if (channel.type == Channel::Redirect) {
|
||||||
// we're redirecting the channel to/from a file
|
// we're redirecting the channel to/from a file
|
||||||
@ -465,18 +477,6 @@ qint64 QProcessPrivate::bytesAvailableFromStdout() const
|
|||||||
#if defined QPROCESS_DEBUG
|
#if defined QPROCESS_DEBUG
|
||||||
qDebug("QProcessPrivate::bytesAvailableFromStdout() == %d", bytesAvail);
|
qDebug("QProcessPrivate::bytesAvailableFromStdout() == %d", bytesAvail);
|
||||||
#endif
|
#endif
|
||||||
if (processChannelMode == QProcess::ForwardedChannels && bytesAvail > 0) {
|
|
||||||
QByteArray buf(bytesAvail, 0);
|
|
||||||
DWORD bytesRead = 0;
|
|
||||||
if (ReadFile(stdoutChannel.pipe[0], buf.data(), buf.size(), &bytesRead, 0) && bytesRead > 0) {
|
|
||||||
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
if (hStdout) {
|
|
||||||
DWORD bytesWritten = 0;
|
|
||||||
WriteFile(hStdout, buf.data(), bytesRead, &bytesWritten, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bytesAvail = 0;
|
|
||||||
}
|
|
||||||
return bytesAvail;
|
return bytesAvail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,18 +490,6 @@ qint64 QProcessPrivate::bytesAvailableFromStderr() const
|
|||||||
#if defined QPROCESS_DEBUG
|
#if defined QPROCESS_DEBUG
|
||||||
qDebug("QProcessPrivate::bytesAvailableFromStderr() == %d", bytesAvail);
|
qDebug("QProcessPrivate::bytesAvailableFromStderr() == %d", bytesAvail);
|
||||||
#endif
|
#endif
|
||||||
if (processChannelMode == QProcess::ForwardedChannels && bytesAvail > 0) {
|
|
||||||
QByteArray buf(bytesAvail, 0);
|
|
||||||
DWORD bytesRead = 0;
|
|
||||||
if (ReadFile(stderrChannel.pipe[0], buf.data(), buf.size(), &bytesRead, 0) && bytesRead > 0) {
|
|
||||||
HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
|
|
||||||
if (hStderr) {
|
|
||||||
DWORD bytesWritten = 0;
|
|
||||||
WriteFile(hStderr, buf.data(), bytesRead, &bytesWritten, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bytesAvail = 0;
|
|
||||||
}
|
|
||||||
return bytesAvail;
|
return bytesAvail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user