diff options
author | Joerg Bornemann <joerg.bornemann@theqtcompany.com> | 2015-06-05 16:57:18 +0200 |
---|---|---|
committer | Joerg Bornemann <joerg.bornemann@theqtcompany.com> | 2015-12-10 16:29:33 +0000 |
commit | 068baa9bb6d526cccc0c8bc7cdbb84bbdf137f95 (patch) | |
tree | 481deaebc9fa5e8036880bf2f9f6b92101c99fce /src/corelib/io | |
parent | 4ae0b655b270d5c8d38903b5ed960971161a672f (diff) |
add a way to modify CreateProcess parameters
[ChangeLog][QtCore][QProcess] Added method
setCreateProcessArgumentsModifier to QProcess on Windows to enable
users to intercept and modify CreateProcess parameters.
With such a modifier, calling code can decide whether to inherit
handles, modify the STARTUPINFO struct, and pass its own
combination of process flags to CreateProcess.
Task-number: QTBUG-390
Task-number: QTBUG-6917
Task-number: QTBUG-9350
Task-number: QTBUG-24619
Change-Id: I14757dbbacfebb1c89f52402d36fba0ba9c45f3a
Reviewed-by: Björn Breitmeyer <bjoern.breitmeyer@kdab.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/io')
-rw-r--r-- | src/corelib/io/qprocess.cpp | 74 | ||||
-rw-r--r-- | src/corelib/io/qprocess.h | 22 | ||||
-rw-r--r-- | src/corelib/io/qprocess_p.h | 1 | ||||
-rw-r--r-- | src/corelib/io/qprocess_win.cpp | 20 |
4 files changed, 111 insertions, 6 deletions
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 952116b9db..315142aabe 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -744,6 +744,47 @@ void QProcessPrivate::Channel::clear() */ /*! + \typedef QProcess::CreateProcessArgumentModifier + \note This typedef is only available on desktop Windows and Windows CE. + + On Windows, QProcess uses the Win32 API function \c CreateProcess to + start child processes. While QProcess provides a comfortable way to start + processes without worrying about platform + details, it is in some cases desirable to fine-tune the parameters that are + passed to \c CreateProcess. This is done by defining a + \c CreateProcessArgumentModifier function and passing it to + \c setCreateProcessArgumentsModifier. + + A \c CreateProcessArgumentModifier function takes one parameter: a pointer + to a \c CreateProcessArguments struct. The members of this struct will be + passed to \c CreateProcess after the \c CreateProcessArgumentModifier + function is called. + + The following example demonstrates how to pass custom flags to + \c CreateProcess. + When starting a console process B from a console process A, QProcess will + reuse the console window of process A for process B by default. In this + example, a new console window with a custom color scheme is created for the + child process B instead. + + \snippet qprocess/qprocess-createprocessargumentsmodifier.cpp 0 + + \sa QProcess::CreateProcessArguments + \sa setCreateProcessArgumentsModifier() +*/ + +/*! + \class QProcess::CreateProcessArguments + \note This struct is only available on the Windows platform. + + This struct is a representation of all parameters of the Windows API + function \c CreateProcess. It is used as parameter for + \c CreateProcessArgumentModifier functions. + + \sa QProcess::CreateProcessArgumentModifier +*/ + +/*! \fn void QProcess::error(QProcess::ProcessError error) \obsolete @@ -1563,6 +1604,39 @@ void QProcess::setNativeArguments(const QString &arguments) d->nativeArguments = arguments; } +/*! + \since 5.7 + + Returns a previously set \c CreateProcess modifier function. + + \note This function is available only on the Windows platform. + + \sa setCreateProcessArgumentsModifier() + \sa QProcess::CreateProcessArgumentModifier +*/ +QProcess::CreateProcessArgumentModifier QProcess::createProcessArgumentsModifier() const +{ + Q_D(const QProcess); + return d->modifyCreateProcessArgs; +} + +/*! + \since 5.7 + + Sets the \a modifier for the \c CreateProcess Win32 API call. + Pass \c QProcess::CreateProcessArgumentModifier() to remove a previously set one. + + \note This function is available only on the Windows platform and requires + C++11. + + \sa QProcess::CreateProcessArgumentModifier +*/ +void QProcess::setCreateProcessArgumentsModifier(CreateProcessArgumentModifier modifier) +{ + Q_D(QProcess); + d->modifyCreateProcessArgs = modifier; +} + #endif /*! diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h index f95358250e..52e0316857 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -38,6 +38,8 @@ #include <QtCore/qstringlist.h> #include <QtCore/qshareddata.h> +#include <functional> + QT_BEGIN_NAMESPACE @@ -48,6 +50,8 @@ typedef qint64 Q_PID; #else QT_END_NAMESPACE typedef struct _PROCESS_INFORMATION *Q_PID; +typedef struct _SECURITY_ATTRIBUTES Q_SECURITY_ATTRIBUTES; +typedef struct _STARTUPINFOW Q_STARTUPINFO; QT_BEGIN_NAMESPACE #endif @@ -180,7 +184,23 @@ public: #if defined(Q_OS_WIN) QString nativeArguments() const; void setNativeArguments(const QString &arguments); -#endif + struct CreateProcessArguments + { + const wchar_t *applicationName; + wchar_t *arguments; + Q_SECURITY_ATTRIBUTES *processAttributes; + Q_SECURITY_ATTRIBUTES *threadAttributes; + bool inheritHandles; + unsigned long flags; + void *environment; + const wchar_t *currentDirectory; + Q_STARTUPINFO *startupInfo; + Q_PID processInformation; + }; + typedef std::function<void(CreateProcessArguments *)> CreateProcessArgumentModifier; + CreateProcessArgumentModifier createProcessArgumentsModifier() const; + void setCreateProcessArgumentsModifier(CreateProcessArgumentModifier modifier); +#endif // Q_OS_WIN QString workingDirectory() const; void setWorkingDirectory(const QString &dir); diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index af88d07a7a..227a583718 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -329,6 +329,7 @@ public: QStringList arguments; #if defined(Q_OS_WIN) QString nativeArguments; + QProcess::CreateProcessArgumentModifier modifyCreateProcessArgs; #endif QProcessEnvironment environment; diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 80e6d5bb61..bb5bb4b0a5 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -497,11 +497,21 @@ void QProcessPrivate::startProcess() 0, 0, 0, stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1] }; - success = CreateProcess(0, (wchar_t*)args.utf16(), - 0, 0, TRUE, dwCreationFlags, - environment.isEmpty() ? 0 : envlist.data(), - workingDirectory.isEmpty() ? 0 : (wchar_t*)QDir::toNativeSeparators(workingDirectory).utf16(), - &startupInfo, pid); + + QProcess::CreateProcessArguments cpargs = { + 0, (wchar_t*)args.utf16(), + 0, 0, TRUE, dwCreationFlags, + environment.isEmpty() ? 0 : envlist.data(), + workingDirectory.isEmpty() ? 0 : (wchar_t*)QDir::toNativeSeparators(workingDirectory).utf16(), + &startupInfo, pid + }; + if (modifyCreateProcessArgs) + modifyCreateProcessArgs(&cpargs); + success = CreateProcess(cpargs.applicationName, cpargs.arguments, cpargs.processAttributes, + cpargs.threadAttributes, cpargs.inheritHandles, cpargs.flags, + cpargs.environment, cpargs.currentDirectory, cpargs.startupInfo, + cpargs.processInformation); + QString errorString; if (!success) { // Capture the error string before we do CloseHandle below |