我想从具有特定PATH设置的Qt应用启动cmd.exe。我在QProcessEnvironment中插入“Path”并将该环境设置为QProcess。然后我startDetached“cmd”。在命令提示符下,路径与调用应用程序的路径相同,而不是我刚刚设置的路径。我错过了什么?我在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);
答案 0 :(得分:3)
startDetached
方法是一种静态方法。因此,您应用于process
对象的所有状态都被忽略,因为该方法无法看到它。如果您使用start()
启动流程,新流程将会启动您的环境。
process.start("cmd", args);
当然,您希望将新进程分离,以便父进程可以在不强制新进程终止的情况下终止。据我所知,QProcess
课程并没有为你提供一种轻松实现这一目标的方法。您可以修改父进程的环境,以便新进程继承这些修改,但这听起来根本不可取。
此问题提供了一种可能的解决方法:Detaching a started process。
答案 1 :(得分:1)
大卫回答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: e.g.
// 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");