Qt Windows application deployment issue. Runs great in Debug, but not fully functional as deployed, stand-alone app
-
Hi again Jon! When I am in the qt Creator IDE, I can run successfully using either "Run" or "Debug" (QProcess::execute() in place in the code). I can also build in either Debug or Release mode, and everything is fine. In the IDE
BTW, sorry I was not complete in my description of my setup. I am running Qt version 6.0.4 , Mingw_64bit in my kit, and under Windows 11. -
@MarkMcC
I misunderstood, I thought the deployed version worked fine but not from IDE. I now see you are saying the opposite.Although it may seem a different issue, both @mchinand & I asked whether you can execute
avrdude
directly without going viacmd /c
? That might simplify matters a bit, and would seem preferable anyway if it works. -
@MarkMcC
Going back toQProcess
. If you want to wait for the process to finish you will need to useQProcess::start()
.startDetached()
won't let you wait.QProcess::execute()
convenience function hides theQProcess
from you. For a start you should check its return value, for all I know it is indicating an error occurred. If you change toQProcess::waitForFinished()
at least you can check for anything it might have written to stdout/err. Maybeavrdude
is writing you a message? Best would be signals/slots, methods ofQProcess
, you just have to keep the instance in scope, say a member variable. I would expect to write it that way if I needed to examine what might be going on from here. -
@mhinand and @JonB
Yes. I had last week I originally wrote the code without the "/C" prefix and my program hung at the QProcess call. I also could see that the activity LED on my dongle at the end of the USB cable was not indicating any traffic, so it too failed to launch.
With the leading "/C", all works. In fact my code above where I replaced "execute" with "startDetached", The argument passed also includes the "/C" prefix.@JonB Sorry about the general confusion. The deployed version is the version which did NOT work with QProcess::execute(), the IDE version does.
-
@MarkMcC said in Qt Windows application deployment issue. Runs great in Debug, but not fully functional as deployed, stand-alone app:
With the leading "/C", all works. In fact my code above where I replaced "execute" with "startDetached", The argument passed also includes the "/C" prefix.
This is not what we are asking you to do. We want to eliminate
cmd
from the problem.Does anything work at all if you try:
Arguments << "-c" << "arduino" << "-P" << "COMPortUsed" << "-b" << "115200" << "-p" << "ATmega328P" << "-e" << "-U" << "eeprom:r:fromEEPROM.bin:r"; int exitCode = CommandPrompt.execute("avrdude",Arguments); qDebug() << exitCode;
-
@JonB ..back at it. I tried the changes above you recommended, and unfortunately, it did not launch AVRDUDE. The exitCode I got back was a "1", measured at a breakpoint I put on the qDebug() << exitCode line. Also, at this point, I examined the "Arguments" QStringList, and I have 11 separate elements there. In mine, I have one contiguous string, delimited by spaces. If I check the exit code after execution, it is a "0".
Also, could you elaborate on your above commentBest would be signals/slots, methods of QProcess, you just have to keep the instance in scope, say a member variable. I would expect to write it that way if I needed to examine what might be going on from here.
I don't follow what you are saying there as it is I'm afraid above my level of c++ programming knowledge. I'm happy to try anything though.
I still find the core of all this, the disconnect between Deployed version versus the running in IDE version pretty baffling. If it was just some screwy code I've written, why would it work under the IDE and then not in the deployment?
-
What is the output of readAllStandardError() and readAllStandardOutput() when the QProcess fails?
-
OK, here is a bit of code I came up with that now works in both in the IDE environment and in the deployed version.
void MainWindow::call_AVRDUDE_write() //AVR WRITE { QProcess CommandPrompt; QStringList Arguments; QString COMPortUsed = (ui->COM_Port_Used->text()); // get the COM port used from the UI Arguments << " /C avrdude -c arduino -P " + COMPortUsed + " -b 115200 -p ATmega328P -e -U eeprom:w:tblXfer.bin:r"; CommandPrompt.start("cmd",Arguments); CommandPrompt.waitForFinished(); }
The last two lines replace the QProcess::execute() line I had earlier that worked only in IDE. What bothers me is that I had tried start() by itself before and it did not work for me, even in IDE environment. I previously tried prefacing it with
CmmandPrompt.setProcessChannelMode(ForwardChannels);
and that seemed to allow me to run start(), and subsequently waitForFinished();
Now I find that actually removing that allows for successful operation
in both IDE and Deployment renditions. Bizzare! This is disturbing because it almost seems like capricious behavior, and I don't like the fact that the change makes such little sense to me. The "problem" seems to be resolved, but I don't have a clue as to why this worked, or for that matter, why there was a disconnect between IDE operation and deployed operation in the first place. @mchinand and @JonB ,Thanks guys for your help. I realize I'm still chasing my tail until this is understood but at least it works (for now). Mark -
@MarkMcC
Some answers to your questions.I tried the changes above you recommended, and unfortunately, it did not launch AVRDUDE. The exitCode I got back was a "1", measured at a breakpoint I put on the qDebug() << exitCode line.
That was always a possibility, and what I was trying to investigate. It implies that
avrdude
is not an executable and has to be invoked viacmd /c
. Which is OK, but complicates matters and makes it harder to know what is going on.Also, at this point, I examined the "Arguments" QStringList, and I have 11 separate elements there. In mine, I have one contiguous string, delimited by spaces.
That is correct. To launch an executable directly via
QProcess
all its command-line arguments must be sent as separate items in aQStringList
. Hence I broke up your command on spaces and separated out all the arguments for you to copy the line. It is only viacmd /c
that one can present the whole command line as a single string instead of separate arguments.If I check the exit code after execution, it is a "0".
One of the disadvantages of running a command via
cmd /c
is that you will always get an exit code of 0 rather than whatever the command being run actually returns as its exit code.Also, could you elaborate on your above comment
I don't follow what you are saying there as it is I'm afraid above my level of c++ programming knowledge.I was asking you to rewrite the
QProcess
call using the signals/slots approaches it offers. That is the low-level on which otherQProcess
calls likeexecute()
andwaitForFinished()
is built, and offers us more control/knowledge over what is going on. However for now at least given that you cannot write it I don't have the time/inclination to write it for you to copy.The last two lines replace the QProcess::execute() line I had earlier that worked only in IDE. What bothers me is that I had tried start() by itself before and it did not work for me, even in IDE environment. I previously tried prefacing it with
CmmandPrompt.setProcessChannelMode(ForwardChannels);
and that seemed to allow me to run start(), and subsequently waitForFinished();
Now I find that actually removing that allows for successful operation
in both IDE and Deployment renditions. Bizzare!Now this is interesting! You say it only works correctly when you do not have
CommandPrompt.setProcessChannelMode(ForwardChannels)
. The utility functionQProcess::execute()
you were previously using does put that line in. If that must not be present, it would explain why your code now differs and works versus usingexecute()
, so at least that is something.You should do one thing. Immediately after your
CommandPrompt.waitForFinished();
you should see whether any messages might have been written to stdout/err by the subprocess. Append these lines:qDebug() << CommandPrompt.readAllStandardOutput(); qDebug() << CommandPrompt.readAllStandardError();
I do not use Windows. I am told that it is difficult to see any output from
qDebug()
when run outside the IDE? If that is so you might have to replace theqDebug()
by something likestd::cout << CommandPrompt.readAllStandardOutput() << std::flush; std::cout << CommandPrompt.readAllStandardError() << std::flush;
(You will need
#include <iostream>
at the head of the.cpp
file.)
Since you say it now actually works withoutCommandPrompt.setProcessChannelMode(ForwardedChannels);
, you may need/want to put that back in when seeing whether there might be any error messages output.I still find the core of all this the core of all this, the disconnect between Deployed version versus the running in IDE version pretty baffling. If it was just some screwy code I've written, why would it work under the IDE and then not in the deployment?
I agree. If I knew what is happening outside the IDE which is different from inside the IDE I would say so!
-
@JonB Thanks Jon. I will look into those suggestions. I think at this point though, the best thing for me to try, rather than thrashing around with my current project, would be for me to start a new project focused on just replicating this specific issue. I'll try and pare this down to minimal required code, just enough to reproduce the problem This will make findings clearer and easier to communicate to others. If I get to a point where I have something useful to share, I'll do so. Thank you again..Mark