【问题标题】:Change PATH environment variable for cmd.exe with QProcessEnvironment使用 QProcessEnvironment 更改 cmd.exe 的 PATH 环境变量
【发布时间】:2014-01-17 11:36:02
【问题描述】:

我想从具有特定 PATH 集的 Qt 应用程序启动 cmd.exe。我在 QProcessEnvironment 中插入“路径”并将该环境设置为 QProcess。然后我开始分离“cmd”。在命令提示符下,路径与调用应用程序的路径相同,而不是我刚刚设置的路径。我错过了什么?我在 Windows 8.1.s 上使用带有 mingw 和 Qt-creator 3.0.0 的 Qt 5.2.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);

【问题讨论】:

    标签: c++ windows qt cmd qprocess


    【解决方案1】:

    startDetached 方法是一个静态方法。因此,您应用于 process 对象的所有状态都将被忽略,因为该方法看不到它。如果您改为使用start() 启动该进程,则新进程将选择您的环境。

    process.start("cmd", args);
    

    当然,您希望分离新进程,以便父进程可以终止,而不会强制新进程也终止。据我所知,QProcess 类并没有为您提供轻松实现这一目标的方法。您可以修改父进程的环境,以便新进程继承这些修改,但这听起来并不理想。

    这个问题提出了一种可能的解决方法:Detaching a started process

    【讨论】:

      【解决方案2】:

      正如大卫回答 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");
      

      【讨论】:

      • 能否请您告诉我如何覆盖 startDetached 函数以接受 Unix 系统中的环境变量。
      猜你喜欢
      • 2021-05-06
      • 2015-09-29
      • 2016-12-29
      • 1970-01-01
      • 1970-01-01
      • 2011-04-19
      • 2016-01-06
      • 1970-01-01
      • 2012-07-09
      相关资源
      最近更新 更多