QProcess can't start HUGE exe, any ideas? It's mame64.exe 130mb in size.
-
I've been tearing my hair out, no matter what I try I can't get QProcess to run an external exe.
Here is from .h
private: QProcess* proc; private slots: void processFromStdOut(); void processFromStdErr(); void processDone(); void processStarted(); void processError(QProcess::ProcessError error);
And here is the main code:
QString path = QString::fromStdString("C:\\mame"); QString exe = QString::fromStdString("mame64.exe"); proc = new QProcess(this); proc->setWorkingDirectory(path); qDebug() << ">>>>> Working Directory:" << path; connect(proc, SIGNAL(readyReadStandardOutput()), this, SLOT(processFromStdOut())); connect(proc, SIGNAL(readyReadStandardError()), this, SLOT(processFromStdErr())); connect(proc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError))); connect(proc, SIGNAL(started()), this, SLOT(processStarted())); connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processDone()));
Below are the slot methods:
void Rommer::processFromStdErr() { qDebug() << proc->readAllStandardError(); } void Rommer::processStarted() { qDebug() << ">>>>> Process Started"; } void Rommer::processDone() { qDebug() << ">>>>> Exit Code:" << proc->exitStatus(); if (proc->exitStatus() == 0) { qDebug() << "Program ran successfully"; } if (proc->exitStatus() == 2) { qDebug() << "Customized message"; } if (proc->exitStatus() == 3) { qDebug() << "Another text warning message"; } } void Rommer::processFromStdOut() { qDebug() << ">>>>> Read from StdOut" << proc->exitStatus(); proc_output = proc->readAllStandardError(); this->add2log("Running: " + proc_output.toStdString(), 2, Qt::GlobalColor::cyan); } void Rommer::processError(QProcess::ProcessError error) { QString errMsg; QString errors[] = { "failed to start", "crashed", "timedout", "read error", "write error", "unknown error" }; errMsg.sprintf("Error: (%d) Process ", error); if (error < sizeof(errors) / sizeof(errors[0])) { errMsg.append(errors[error].toLocal8Bit().constData()); } else { errMsg.append("error"); } qDebug() << errMsg; emit updateStatusSignal(errMsg); }
No matter what way I try and start the QProcess it won't start, just using .start fails to start the process.
I can start other exe but with the mame exe I am telling it too produce a massive xml file and redirecting the output. The exe is huge, 130mb, but I have 32gb of memory is there something I should tweak to get this to run? p.s it's nothing to do with the pipe to a file, it's something to do with the way the exe is created / or size???? Any ideas how to get it to work would be appreciated. Thanks
-
@jonndoe47
In all your code there is noproc.start()
called on yourproc = new QProcess(this);
. Nor is there any use of yourQString exe
variable. So where do you expect to attempt to start any process? As it stands it's not going to run anything. -
@jonndoe47 said in QProcess can't start HUGE exe, any ideas? It's mame64.exe 130mb in size.:
mame64.exe
Hi
Is mame64.exe your own Qt exe ? -
No, mame64.exe is an emulator that is free to use and source code available i believe on github, it runs in size to about 130mb. I don't know how it's constructed as I just d/l the binary for it. I'm construct a rom manager and need to be able to call it both to run roms and also to get the xml rom list to parse it so I can manage these roms.
Probably missed the proc start when I was cutting / pasting.
- It does run exe's, it runs notepad fine.
- It will not run at all mame64.exe , i have used proc start and proc execute, I stated this earlier.
- WHen I use proc start, it gives failed to start immediately.
- If I use proc execute it just does nothing, no error message at all. Nothing.
-
@jonndoe47 Is processError called?
-
Below is the two run results from the debug window in VS.
The first is when I use proc start. The second is when I use proc execute.
Notice the second time round, using proc execute, doesn't call
Rommer::processError(QProcess::ProcessError error) via the slot, it just falls straight through.'QtGuiApplication1.exe' (Win32): Loaded 'C:\VS Projects\QtGuiApplication1\x64\Debug\QtGuiApplication1.exe'. Symbols loaded. 'QtGuiApplication1.exe' (Win32): Loaded 'C:\Windows\System32\ntdll.dll'. <<<REMOVED LOADED MESSSAGES>>> >>>>> Working Directory: "C:\\mame" "Error: (0) Process failed to start" >> Could not Start 'QtGuiApplication1.exe' (Win32): Loaded 'C:\VS Projects\QtGuiApplication1\x64\Debug\QtGuiApplication1.exe'. Symbols loaded. 'QtGuiApplication1.exe' (Win32): Loaded 'C:\Windows\System32\ntdll.dll'. <<<REMOVED LOADED MESSSAGES>>> 'QtGuiApplication1.exe' (Win32): Loaded 'C:\Windows\System32\iertutil.dll'. >>>>> Working Directory: "C:\\mame" >> Could not Start
-
@jonndoe47 Can you start this application manually in command line? Maybe it is broken or some dependencies are missing?
-
Yes I can start the program via either by double clicking on it in windows explorer, or via dos prompt. And I know that there are rom managers that can call the exe. Is there any other option apart from QProcess ? I tried _popen but it didn't work within Qt as Qt has it's own process loop.
-
@jonndoe47
To help you try to debug this nasty.i have used proc start
Would you please show the line where you use
proc.start()
, or log it. I'd like to see the exact command line/parameters etc.Since the supposed most likely for this is simply "file does not exist", if I see that that current directory is
path
and you are trying to runexe
could you humour us by doing aQFileInfo
onexe
variable, as passed tostart()
, so that we can see it showing file exists?mame64.exe
likely requires some DLLs to run, and may find them onPATH
? Do we know that thePATH
from your Qt program matches whatever when you run it from a Command Prompt and it works?I assume you have tried this outside of VS as well as inside it? And what about for Release vs Debug?
Add slot for signal https://doc.qt.io/qt-5/qprocess.html#stateChanged. You want to see whether there is any state changing going on, as this may give a clue to code path.
There is a very small chance that Windows is logging something, check in Event Viewer.
Change what you execute to be
start("cmd", QStringList() << "/c" << "mame64.exe")
. Any difference in behaviour, does thecmd
report anything to your output redirections?Replace your attempt to run
mame64.exe
directly by amame.bat
in the same directory as it, which just runs the EXE from the BAT file. You may be able to get more clues about what is going on from a BAT.https://code.woboq.org/qt5/qtbase/src/corelib/io/qprocess_win.cpp.html gives the code for Windows. You are looking for
QProcess::FailedToStart
. I do not compile Qt sources, but if you do you may be able to break in https://code.woboq.org/qt5/qtbase/src/corelib/io/qprocess.cpp.html#_ZN15QProcessPrivate15setErrorAndEmitEN8QProcess12ProcessErrorERK7QString and see what's going on. -
Ok, below is the code. I just ran this first against notepad.exe in C:\Windows and it worked. Then I changed the code to run it against mame.bat in C:\mame. It did not work. The first line I commented out was I tried with C:/mame/ just in case some weird thing, but that was commented out also is debug info to show file exists:
Code below:
// QString path = QString::fromStdString("C:/mame/"); i tried this first QString path = QString::fromStdString("C:\\mame\\"); QString exe = QString::fromStdString("mame.bat"); proc = new QProcess(this); proc->setWorkingDirectory(path); QFileInfo fi(path+exe); qDebug() << "filename " << fi.fileName(); qDebug() << "absolute path : " << fi.absolutePath(); qDebug() << "file path : " << fi.filePath(); qDebug() << "exists " << fi.exists(); qDebug() << ">>>>> Working Directory:" << path; connect(proc, SIGNAL(readyReadStandardOutput()), this, SLOT(processFromStdOut())); connect(proc, SIGNAL(readyReadStandardError()), this, SLOT(processFromStdErr())); connect(proc, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError))); connect(proc, SIGNAL(started()), this, SLOT(processStarted())); connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processDone())); proc->start(exe); if (proc->waitForStarted(60000) == true) { qDebug() << ">> Started ok"; } else { qDebug() << ">> Could not Start"; } //proc->close(); /* if (_proc->waitForStarted() == true) { qDebug() << ">>> Process Started ok"; } */ } void Rommer::processFromStdErr() { qDebug() << proc->readAllStandardError(); } void Rommer::processStarted() { qDebug() << ">>>>> Process Started"; } void Rommer::processDone() { qDebug() << ">>>>> Exit Code:" << proc->exitStatus(); if (proc->exitStatus() == 0) { qDebug() << "Program ran successfully"; } if (proc->exitStatus() == 2) { qDebug() << "Customized message"; } if (proc->exitStatus() == 3) { qDebug() << "Another text warning message"; } } void Rommer::processFromStdOut() { qDebug() << ">>>>> Read from StdOut" << proc->exitStatus(); proc_output = proc->readAllStandardError(); this->add2log("Running: " + proc_output.toStdString(), 2, Qt::GlobalColor::cyan); } void Rommer::processError(QProcess::ProcessError error) { QString errMsg; QString errors[] = { "failed to start", "crashed", "timedout", "read error", "write error", "unknown error" }; errMsg.sprintf("Error: (%d) Process ", error); if (error < sizeof(errors) / sizeof(errors[0])) { errMsg.append(errors[error].toLocal8Bit().constData()); } else { errMsg.append("error"); } qDebug() << errMsg; emit updateStatusSignal(errMsg); } Here is the debug stuff: ```'QtGuiApplication1.exe' (Win32): Loaded 'C:\Windows\System32\iertutil.dll'. filename "mame.bat" absolute path : "C:/mame" file path : "C:/mame/mame.bat" exists true >>>>> Working Directory: "C:\\mame\\" "Error: (0) Process failed to start" >> Could not Start 'QtGuiApplication1.exe' (Win32): Unloaded 'C:\Windows\System32\imagehlp.dll' 'QtGuiApplication1.exe' (Win32): Unloaded 'C:\Windows\System32\wintrust.dll' 'QtGuiApplication1.exe' (Win32): Unloaded 'C:\Windows\System32\msasn1.dll' 'QtGuiApplication1.exe' (Win32): Unloaded 'C:\Windows\System32\crypt32.dll' The thread 0x1f7c has exited with code 0 (0x0). The thread 0xb24 has exited with code 0 (0x0). The thread 0x21f8 has exited with code 0 (0x0). The thread 0x7a8 has exited with code 0 (0x0).
mame.,bat just contains 1 line "mame64.exe", both the batch file and the exe run from either windows explorer or DOS. The mame64.exe is stand alone and there are no dll's or anything with it. If anyone wants to try it themselves the exe is hosted here: https://www.mamedev.org/ I use the 64 bit version , it's just an emulator but it is 130mb in size. And no, it has no viruses.
-
@jonndoe47
You are runningproc->start(exe);
but you reportQFileInfo fi(path+exe);
. Please don't do that. I wroteon
exe
variable, as passed tostart()
I cannot write every time, you need to test the same things, that's the whole point of the suggestion.
Have you at least tried running as
start(path+exe)
, instead of relying on current directory?If you are showing that now it cannot run your
mame.bat
, whatever that contains, then the issue has nothing to do with yourmame64.exe
.... -
-
@jonndoe47
I thought it was a path issue, and running by full path is one of the first things I would have tried.I don't know: Did you try working directory as
"C:\\mame"
, just in case it does not like the trailing backslash (I think you did at one point)? Do you by any chance start from a different drive letter fromC:
? Try running aCD
as the command and see what it reports? Run aDIR
as the command and see what is in its current directory? I doubt there will be a flaw in Qt'ssetWorkingDirectory()
.I'm not even 100% sure that it sets the working directory before it finds the executable to run, though I did think it would. If it does not, that would explain.
-
-
@jonndoe47
I thinkQProcess::setWorkingDirectory()
does not, or you cannot assume it does, set the working directory before it finds the executable, whether that be in current directory or alongPATH
. At least under Windows.It is thus not quite the same as you going into a Command Prompt and typing
cd somewhere run-something-here-by-plain-name
Rather, I think it is like
if not find executable in (calling process) current directory or along PATH return failed-to-find else cd to specified directory run executable
Current directory will initially be that of your project, so it won't see
mame64.exe
inC:\mame
.That's my guess. You could test to see. Moral: don't rely on running executable by plain name which will be in the directory you pass to
setWorkingDirectory()
, instead specify absolute path to where executable is.EDIT I found confirmation of this behaviour of
QProcess::setWorkingDirectory()
in, say, https://www.qtcentre.org/threads/7-QProcess-problem-with-windows-batch-file, going back all the way to Qt3 2006. E.g.QProcess always looks for the file from the working directory of the process in which QProcess runs. And what QProcess::setWorkingDirectory sets is the working directory of the created process, they are different.
Oh, you're calling a QProcess::setWorkingDirectory() method... You're right then, it doesn't influence where QProcess looks for the program. -
In your last code example you showed that you are trying to run
mame.bat
and notmame64.exe
. I am not entirely sure, but I believe that batch files can only be executed within a command shell. This would work from the command prompt directly and also by double-clicking in Explorer as this would know to hand the batch file tocmd
. But, I assume thatQProcess
is only able to launch executables (it would have no way to know which shell (cmd
or PowerShell) to invoke and does not even have any knowledge that the file you provided is a batch file at all).Basically, either you call the
.exe
directly or you callcmd
and hand over the batch file (for callingcmd
correctly see one of the posts above). -
@SimonSchroeder
You are right (unless it has changed in a Qt version), you must run a.bat
viacmd /c
. However --- I cannot test, I don't have Windows Qt --- what I don't understand in that light is the Qt docs examples at https://doc.qt.io/qt-5/qprocess.html#start-1process.start("del /s *.txt"); process.start("dir \"My Documents\"");
del
&dir
arecmd
-builtins, not external.exe
s. Therefore they should not be executable withoutcmd /c
, just like for a.bat
file? Are you able to test whether these actually work from Qt under Windows? -
@JonB said in QProcess can't start HUGE exe, any ideas? It's mame64.exe 130mb in size.:
del & dir are cmd-builtins, not external .exes
CreateProcess knows about them, so it can execute them. On the other hand the windows API has no knowledge of your batch file, it even says so in the WinAPI docs (sourced here), that you must explicitly run the command-line interpreter with the proper arguments to execute a .bat file.
Are you able to test whether these actually work from Qt under Windows?
They work, I can assure you.