1

Using QProcess::startDetached, I need to pass a dynamic argument list which is coming from another process to the starting process.

const QString & prog, const QStringList & args, const QString & workingDirectory ...)

Note that arguments that contain spaces are not passed to the process as separate arguments.

...

Windows: Arguments that contain spaces are wrapped in quotes. The started process will run as a regular standalone process.

I have a string which contains below text, It comes from an external program without any control on it:

-c "resume" -c "print 'Hi!'" -c "print 'Hello World'"

I need to pass above string to QProcess::startDetached so that the starting program catches it as same as above string.

Do I have to parse the string and build a string-list? Or anyone has a better solution?

masoud
  • 55,379
  • 16
  • 141
  • 208

2 Answers2

2

You don't have to use a QStringList at all for the arguments, as there is this overloaded function: -

bool QProcess::startDetached(const QString & program)

Which, as the documentation states: -

Starts the program program in a new process. program is a single string of text containing both the program name and its arguments. The arguments are separated by one or more spaces.

The program string can also contain quotes, to ensure that arguments containing spaces are correctly supplied to the new process.

You may need to replace " with \", but you can do that from a QString

 

You can use parseCombinedArgString (from Qt's source code) to parse:

QStringList parseCombinedArgString(const QString &program)
{
    QStringList args;
    QString tmp;
    int quoteCount = 0;
    bool inQuote = false;
    // handle quoting. tokens can be surrounded by double quotes
    // "hello world". three consecutive double quotes represent
    // the quote character itself.
    for (int i = 0; i < program.size(); ++i)
    {
        if (program.at(i) == QLatin1Char('"'))
        {
            ++quoteCount;
            if (quoteCount == 3)
            {
                // third consecutive quote
                quoteCount = 0;
                tmp += program.at(i);
            }
            continue;
        }
        if (quoteCount)
        {
            if (quoteCount == 1)
                inQuote = !inQuote;
            quoteCount = 0;
        }
        if (!inQuote && program.at(i).isSpace())
        {
            if (!tmp.isEmpty())
            {
                args += tmp;
                tmp.clear();
            }
        }
        else
        {
            tmp += program.at(i);
        }
    }
    if (!tmp.isEmpty())
        args += tmp;
    return args;
}
masoud
  • 55,379
  • 16
  • 141
  • 208
TheDarkKnight
  • 27,181
  • 6
  • 55
  • 85
  • How about the overload which has `workingDirectory` parameter? Can I have the overload that you mentioned and set the working directory? – masoud Mar 27 '14 at 11:26
  • There is a separate function call QProcess::setWorkingDirectory: "Sets the working directory to dir. QProcess will start the process in this directory." So call that before you call call startDetached. However, you may need to create an instance of QProcess for this to work. – TheDarkKnight Mar 27 '14 at 11:30
  • `startDetached` is a static method, are you sure that it uses the internal attributes of `QProcess` for `startDetached`? – masoud Mar 27 '14 at 11:44
  • A good point. According to this thread, it was a defined as a bug in 2010, but may have been fixed. If not, it suggests to overload the function to support it yourself: http://stackoverflow.com/questions/4265946/set-environment-variables-for-startdetached-qprocess – TheDarkKnight Mar 27 '14 at 11:52
  • Looking at the source code, at line 2151, the environment variable is still ignored: https://qt.gitorious.org/qt/qt/source/ec76b17145c6449a5d90a1052635f30971e7fa4d:src/corelib/io/qprocess.cpp#L5 – TheDarkKnight Mar 27 '14 at 11:58
  • However, you could copy the function parseCombinedArgString from line 1906 to create the arg list for you and just call the startDetached with the arg list and environment. – TheDarkKnight Mar 27 '14 at 11:59
1

Yes you have to "parse" the string, splitting it at the correct positions, and enter each sub-string into the QStringList object you pass to the function.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Isn't it weird? Passing an argument string usually is a very easy task. Why `startDetached` needs `QStringList` as all? How about more complicated arguments? – masoud Mar 27 '14 at 11:21
  • @MM. Probably because the function can't reasonably parse the argument string if it creates an `argv`-style array. – Some programmer dude Mar 27 '14 at 11:23
  • +1 I've used `parseCombinedArgString` from Qt's source code which parses the string. You're right that I have to parse it. – masoud May 07 '14 at 06:28