Change PATH environment variable for cmd.exe with QProcessEnvironment

前端 未结 2 1232
小蘑菇
小蘑菇 2021-01-26 12:15

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

2条回答
  •  无人及你
    2021-01-26 13:03

    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");
    

提交回复
热议问题