Solved Problem passing a directory with whitespace in QProcess
-
Hello
It's been a week that I'm developing an ESP32 binary burner with flash encryption. Basically it just wrapper for Python script that provided by espressif so I don`t need to manually call all the flash encryption function one by one. To avoid Python dependencies, I build .py files into .exe.
Long story short, I have succesfully create QT program for ESP32 binary burner. The problem is, when I deploy the program into another PC, my program fail miserably. After further investigation, it was found that there is problem when I have a whitepsace on the python argument. So I`m looking for solution, and found this thread: https://forum.qt.io/topic/40197/problem-passing-a-directory-with-a-space-in-it-as-an-argument
Basically the solution is making a batch script file (.cmd) to catch all the argument and paste them together. And it works...
...Until I realize that .cmd need to be on the folder with NO whitespace.
Sure I can put my .cmd in C:/ and call it a day. But I want to make sure all the main program, QT dll, python script and .cmd (if needed) into one folder so when deploying to another PC, I just need to copy one folder and be done with it.
Here is snipset on the QT Program. This is a simple hard coded program (the real program using QCoreApplication::applicationDirPath() for path), but will give you the idea how I want it to work:
ESPTS::ESPTS(QWidget *parent) : QWidget(parent), ui(new Ui::ESPTS) { ui->setupUi(this); proc = new QProcess(this); connect(proc, SIGNAL(readyReadStandardOutput()), this, SLOT(rightMessage())); connect(proc, SIGNAL(readyReadStandardError()), this, SLOT(wrongMessage())); connect(proc, SIGNAL(finished(int)), this, SLOT(finishedMessage())); QString espefuse_path = "C:/Users/Krisna/Desktop/ESP Burner/espefuse.exe"; //Whitespace on ESP Burner Folder QString espcommand_path = "C:/Users/Krisna/Desktop/ESP Burner/espcommand.cmd"; //Whitespace on ESP Burner Folder //QString espcommand_path = "C:/espcommand.cmd"; //No whitespace, it works QString exec = "cmd.exe /C " + espcommand_path + " summary" + " \"" + espefuse_path + "\"" + " \"" + "COM54" + "\"" ; esp32_message.clear(); //To catch all data from QProcess ui->textEdit->append(exec); ui->textEdit->append(""); //For debugging proc->start(exec); } ESPTS::~ESPTS() { delete ui; } void ESPTS::rightMessage() { QByteArray strdata = proc->readAllStandardOutput(); strdata = strdata.simplified(); strdata = strdata.trimmed(); esp32_message.append(strdata); //Append QProcess data } void ESPTS::wrongMessage() { QByteArray strdata = proc->readAllStandardError(); esp32_message.append(strdata); //Append QProcess data } void ESPTS::finishedMessage() { ui->textEdit->append(esp32_message); //Show the results }
Here is the snipset on .cmd file:
@echo off call :%1 %2 %3 %4 %5 %6 %7 %8 %9 goto :eof :summary "%~1" --port %~2 summary goto :eof
So when I run the program, ui->textEdit showing the result as following:
cmd.exe /C C:/Users/Krisna/Desktop/ESP Burner/espcommand.cmd summary "C:/Users/Krisna/Desktop/ESP Burner/espefuse.exe" "COM54" 'C:/Users/Krisna/Desktop/ESP' is not recognized as an internal or external command, operable program or batch file.
Any help will be greatly appreciated. Thank you for your time and guidance. Sorry for my bad english.
-
@Papatonk You need to put such paths in "":
QString espefuse_path = "\"C:/Users/Krisna/Desktop/ESP Burner/espefuse.exe\"";
-
@jsulm Thank you for your reply. So using:
QString espefuse_path = "\"C:/Users/Krisna/Desktop/ESP Burner/espefuse.exe\""; //Whitespace on ESP Burner Folder QString espcommand_path = "C:/Users/Krisna/Desktop/ESP Burner/espcommand.cmd"; //Whitespace on ESP Burner Folder //QString espcommand_path = "C:/espcommand.cmd"; //No whitespace, it works
Give the same result:
cmd.exe /C C:/Users/Krisna/Desktop/ESP Burner/espcommand.cmd summary ""C:/Users/Krisna/Desktop/ESP Burner/espefuse.exe"" "COM54" 'C:/Users/Krisna/Desktop/ESP' is not recognized as an internal or external command, operable program or batch file.
And if I add " to espcommand_path
QString espefuse_path = "\"C:/Users/Krisna/Desktop/ESP Burner/espefuse.exe\""; //Whitespace on ESP Burner Folder QString espcommand_path = "\"C:/Users/Krisna/Desktop/ESP Burner/espcommand.cmd\""; //Whitespace on ESP Burner Folder
Give the same result too:
cmd.exe /C "C:/Users/Krisna/Desktop/ESP Burner/espcommand.cmd" summary ""C:/Users/Krisna/Desktop/ESP Burner/espefuse.exe"" "COM54" '"C:/Users/Krisna/Desktop/ESP"' is not recognized as an internal or external command, operable program or batch file.
-
@Papatonk said in Problem passing a directory with whitespace in QProcess:
QString exec = "cmd.exe /C " + espcommand_path + " summary"
+ " "" + espefuse_path + """
+ " "" + "COM54" + """This is completely wrong! Please read https://doc.qt.io/qt-5/qprocess.html
Hint: the command to execute and its parameters are NOT one string! Parameters need to be put into a QStringList parameter. -
@jsulm Ok, actually I have play with QProcess with QStringList before, AFAIK we dont need to put ", QProcess will do that when we pass QStringList, but CMIIW. So here is the code:
QString espefuse_path = "C:/Users/Krisna/Desktop/ESP Burner/espefuse.exe"; //Whitespace on ESP Burner Folder QString espcommand_path = "C:/Users/Krisna/Desktop/ESP Burner/espcommand.cmd"; //Whitespace on ESP Burner Folder QStringList exec_list; exec_list << "/C" << espcommand_path << "summary" << espefuse_path << "COM54"; proc->start("cmd.exe", exec_list);
Still give the same result:
'C:/Users/Krisna/Desktop/ESP' is not recognized as an internal or external command, operable program or batch file.
-
This post is deleted! -
Apart from all the comments above - why do you need
cmd /c
at all here? Why not simply start the executable. For the cmd it's needed but not for the exe. -
@Papatonk
I would not try passing a path with/
s in it to Windows/cmd. To ensure it's treated correctly you should use\
s. QtQString QDir::toNativeSeparators(const QString &pathName)
can do this for you.But mostly I would follow @Christian-Ehrlicher's suggestion. At the moment your command seems to have no need of being run via
cmd /c
(e.g. no redirection symbols used). So execute it directly and see how the quoting comes out. -
@Christian-Ehrlicher Because I'm such a noob, the only QProcess I know is using only cmd.exe :D. Man it's embarassing, it's solved now. Sorry for bothering all of you, thank you for your guidance.
-
@Papatonk
No worries. we don't mind beginners as long as they post the actual code and write clear questions and not
respond to all suggestions with "Don't work" :)
So just consider yourself a little less beginner now :)