Running commands in CMD prompt with QProcess
-
Hi,
In Windows, I need to run a .sh script inside of Qt Creator with QProcess for an application (this application will be used in computers that have the same configuration and capability for running .sh scripts)The context is: I need to run this particular shell script with CMD prompt, because if I use Cygwin or Git Bash to run it it won't work (because of a command that contains a path, and I don't want to do modifications around that, I want to use CMD to run the .sh script, and I've tested using CMD to run the contents of the sh script and it works correctly.).
I first wanted to check how to open a cmd.exe in QProcess and send a simple command ("/c echo %path% > C:/path.txt")
However I tested different attempts in QT Creator (running QT Creator as an administrator also, to check if that may interfer with my code not working).QProcess* testProcess = new QProcess(this); testProcess->setWorkingDirectory(workingDir); testProcess->start("cmd.exe", QStringList("/c echo %path% > C:/path.txt"));
I tested also having the cmd's full path ("C:/Windows/system32/cmd.exe") and it didn't work.
I also tried using directly a testProcess->execute() command, but it didn't work.Do you have any suggestions for how to send commands in CMD?
Thank you.
-
@ayonsand said in Running commands in CMD prompt with QProcess:
QStringList("/c echo %path% > C:/path.txt")
All parameters to the command have to be string elements in a QStringList, not just one string element.
Probably like this:QStringList() << "/c" << "echo %path% > C:/path.txt"
-
@jsulm , @ayonsand
Because this string is passed straight to cmd/Windows, youwillmay need correct Windows path syntax:QStringList() << "/c" << "echo %path% > C:\\path.txt"
If you have a Qt-style-
/
string for the redirection path use QString QDir::toNativeSeparators(const QString &pathName).Technically whether you get away with
/
instead of\
depends on the command. Compare, for example, the behaviour ofdir /s dir \s
Not at all the same!
-
@jsulm said in Running commands in CMD prompt with QProcess:
"echo %path% > C:/path.txt"
Hi, one question: I followed the same structure I had when my simple code worked (with the path.txt) but replaced the arguments with the shell script I need to run in cmd.exe:
QStringList testArgs; QString mcase = "HP_v1.set"; testArgs.append("/c"); testArgs.append("sh mcase.sh " + mcase); QProcess* testProcess = new QProcess(this); testProcess->setWorkingDirectory(workingDir); testProcess->start("cmd.exe", testArgs);
This was the same structure I followed with the simple command (the second argument being "echo %path% > C:/path.txt")
But when I execute this it doesn't work (it is expected to create an output file in the working directory). I also tried with the "mcase.sh" and mcase full paths, but didn't work.
Do you know what could be happening?Thanks!
-
@ayonsand said in Running commands in CMD prompt with QProcess:
But when I execute this it doesn't work (it is expected to create an output file in the working directory).
We do not know this from what you show.
I strongly advise you to put in code to read whatever might be being output by either
cmd
,sh
or your script. InQProcess
seereadyReadStandardOutput()
,readyReadStandardError()
and alsoerrorOccurred()
(unlikely here as you are usingcmd
). These only work when the command completes, either attach a slot tofinished()
signal or if you are lazy usewaitForFinished()
at least while you debug.Also once you have output if your
sh
is any good (I don't know under Windows) you could use arguments like-e
or-x
(or correspondingset
commands inside script) to trace what is happening in the script if necessary, -
@JonB
If I add waitForFinished(-1) while debugging, the program gets stuck there as it seems it's not finishing the process. It does start it (with waitForStarted)I added these lines as well (but it never gets to that because the program gets stuck in the waitForFinished line),
MCASEProcess->waitForFinished(-1); exitCode = testProcess->exitCode(); // Print debugging information qDebug() << "Exit code:" << exitCode; qDebug() << "Standard error:" << testProcess->readAllStandardError(); qDebug() << "Standard output:" << testProcess->readAllStandardOutput();
if I delete the waitForFinished line it sends the following output (Exit code: 0
Standard error: ""
Standard output: "")the contents of the shell file:
#!/bin/bash # This script calls application [STRUCTUREANALYSIS] and receive as argument the name of .SET file to read # The expected output is a .dat file. Run as sh mcase.sh your_file.set structureanalysis MCASE << EOF .SET $1 QUIT EOF
When I run the command sh mcase.sh my_file.set manually in CMD, it does work and generates a .dat output in my wg directory (if I do it in Cygwin/Git Bash directly it doesn't work, because of the way paths are handled differently)
-
@ayonsand said in Running commands in CMD prompt with QProcess:
Standard output: "")
That looks a bit like some message, but cut off? OIC, maybe the
)
is just part of the original message, not genuinely output.If
finshed()
signal/waitForFinished(-1)
are not returning, change code to read the outputs onto slots attached toreadyRead...Output()
class. You must do this: placingread...()
immediately afterstart()
is no good. Or you could pass a non--1
timeout towaitForFinished()
if your command completes in reasonable time. That's the best you can do. Output might still be buffered at thesh
side, we don't know.Try putting
set -x
set +x
as first statement in script. Hoping to see where it gets to.As ever, simplify while diagnosing. Try just
echo "Hello world"
as whole script content. Try justpwd
. Tryecho "$1"
. Trycat << EOF Cruel world EOF
as script content. Etc.
CORRECTION
I said to putset -x
into script file. I think that is wrong. It is eithersh -x ...
on the command line orset +x
if inside file. -
@JonB Ohh, what I meant is this:
(
Exit code: 0
Standard error: ""
Standard output: ""
)Anyways, I tested using another script like you suggested, and you're right, it is working (redirected the output to a .txt file and it is generating correctly)
I'm thinking the issue in the original script may be something related to the path of "structureanalysis" path variable, is there any way to display the command prompt that is opening with QProcess? To check what error message it's displaying?
-
@ayonsand
No "command prompt" should be opening when you execute this. If one does, that would come fromstructureanalysis
. To get any messages you must grab output as I wrote. Or I suppose you could execute something likecmd /c "sh ... 1>C:\temp\stdout 2>C:\temp\stderr"
I have suggested you should put
set +x
as the first line of your script to try to discover what is going on. Have you done that?If your command is nothing other than
sh abc.sh def.set
(e.g. no redirections) you should not needcmd /c
to run it. You might trytestProcess ->start("sh", QStringList() << shFile << setFile);
to eliminate the
cmd
. Don't klnow if that would behave any differently. -
@JonB Hi, thanks for all the help, I finally figured it out, it did have to do with the env variable for structureanalysis, even if I ran it inside cmd there was trouble. I had to send the full path for where structureanalysis is located in my shell script. it worked