I want to start cmd.exe from a Qt app with a specific PATH set. I insert \"Path\" in QProcessEnvironment and set that environment to QProcess. Then I startDetached \"cmd\". On t
As David answered startDetached
doesn't use the environment. So I went and take the original code and adjusted it a bit so it works (for me at least).
WProcess.h:
#ifndef WPROCESS_H
#define WPROCESS_H
#include
class WProcess
{
public:
WProcess();
void setProcessEnvironment(const QProcessEnvironment &value) {environment = value;}
bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDir);
private:
QProcessEnvironment environment;
};
#endif // WPROCESS_H
WProcess.cpp:
#include "WProcess.h"
#include
#include
static QString w_create_commandline(const QString &program, const QStringList &arguments)
{
QString args;
if (!program.isEmpty()) {
QString programName = program;
if (!programName.startsWith(QLatin1Char('\"')) && !programName.endsWith(QLatin1Char('\"')) && programName.contains(QLatin1Char(' ')))
programName = QLatin1Char('\"') + programName + QLatin1Char('\"');
programName.replace(QLatin1Char('/'), QLatin1Char('\\'));
// add the prgram as the first arg ... it works better
args = programName + QLatin1Char(' ');
}
for (int i=0; i 0 && tmp.at(i - 1) == QLatin1Char('\\'))
--i;
tmp.insert(i, QLatin1Char('"'));
tmp.prepend(QLatin1Char('"'));
}
args += QLatin1Char(' ') + tmp;
}
return args;
}
static QByteArray w_create_environment(const QProcessEnvironment &environment)
{
QByteArray envlist;
if (!environment.isEmpty())
{
static const wchar_t equal = L'=';
static const wchar_t nul = L'\0';
int pos = 0;
QStringList keys = environment.keys();
foreach(QString key, keys)
{
QString value = environment.value(key);
uint tmpSize = sizeof(wchar_t) * (key.length() + value.length() + 2);
// ignore empty strings
if (tmpSize != sizeof(wchar_t) * 2)
{
envlist.resize(envlist.size() + tmpSize);
tmpSize = key.length() * sizeof(wchar_t);
memcpy(envlist.data() + pos, key.utf16(), tmpSize);
pos += tmpSize;
memcpy(envlist.data() + pos, &equal, sizeof(wchar_t));
pos += sizeof(wchar_t);
tmpSize = value.length() * sizeof(wchar_t);
memcpy(envlist.data() + pos, value.utf16(), tmpSize);
pos += tmpSize;
memcpy(envlist.data() + pos, &nul, sizeof(wchar_t));
pos += sizeof(wchar_t);
}
}
// add the 2 terminating 0 (actually 4, just to be on the safe side)
envlist.resize( envlist.size()+4 );
envlist[pos++] = 0;
envlist[pos++] = 0;
envlist[pos++] = 0;
envlist[pos++] = 0;
}
return envlist;
}
WProcess::WProcess()
{
}
bool WProcess::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir)
{
QByteArray envlist;
if (!environment.isEmpty())
{
envlist = w_create_environment(environment);
}
QString args = w_create_commandline(program, arguments);
bool success = false;
PROCESS_INFORMATION pinfo;
STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
(ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
(ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
success = CreateProcess(0, (wchar_t*)args.utf16(),
0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE,
envlist.isEmpty() ? 0 : envlist.data(),
workingDir.isEmpty() ? 0 : (wchar_t*)workingDir.utf16(),
&startupInfo, &pinfo);
if (success)
{
CloseHandle(pinfo.hThread);
CloseHandle(pinfo.hProcess);
//if (pid) *pid = pinfo.dwProcessId;
}
return success;
}
Usage, open command prompt in C:\Qt\Qt-creator and set path to "mypath".
WProcess process;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert("Path", "mypath");
process.setProcessEnvironment(env);
process.startDetached("cmd", QStringList(), "C:\\Qt\\Qt-creator");