使用QProcessEnvironment更改cmd.exe的PATH环境variables

我想从Qt应用程序启动具有特定path的cmd.exe。 我在QProcessEnvironment中插入“path”并将该环境设置为QProcess。 然后我开始读取“cmd”。 在命令提示符下,path与调用应用程序的path相同,而不是我刚刚设置的path。 我错过了什么? 我在windows 8.1.s上使用了Qt 5.2.0与mingw和Qt-creator 3.0.0

QProcess process(this); QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert("Path", "MyPath"); process.setProcessEnvironment(env); QStringList args; args << "/D" << "/K" << "dir"; process.startDetached("cmd", args); 

startDetached方法是一个静态方法。 所以你应用到process对象的所有状态都被忽略,因为方法看不到它。 如果你用start()来启动这个进程,那么新的进程将会启动你的环境。

 process.start("cmd", args); 

当然,你希望新的进程被分离,这样父进程可以终止而不强制新进程也终止。 从我所知道的情况来看, QProcess类并不能为您提供一种轻松实现的方法。 您可以修改父进程的环境,以便新进程继承这些修改,但听起来并不令人满意。

这个问题提出了一个可能的解决方法: 分离已启动的进程 。

由于David回答startDetached不使用这个环境。 所以我去了原来的代码,并调整了一下,所以它的作品(至少对我来说)。

WProcess.h:

 #ifndef WPROCESS_H #define WPROCESS_H #include <QProcessEnvironment> 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 <Windows.h> #include <WinBase.h> 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<arguments.size(); ++i) { QString tmp = arguments.at(i); // Quotes are escaped and their preceding backslashes are doubled. tmp.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\\"")); if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) { // The argument must not end with a \ since this would be interpreted // as escaping the quote -- rather put the \ behind the quote: eg // rather use "foo"\ than "foo\" int i = tmp.length(); while (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; } 

用法,在C:\ Qt \ Qt-creator中打开命令提示符并设置路径为“mypath”。

 WProcess process; QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert("Path", "mypath"); process.setProcessEnvironment(env); process.startDetached("cmd", QStringList(), "C:\\Qt\\Qt-creator");