Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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 no proc.start() called on your proc = new QProcess(this);. Nor is there any use of your QString exe variable. So where do you expect to attempt to start any process? As it stands it's not going to run anything.


  • Lifetime Qt Champion

    @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.

    1. It does run exe's, it runs notepad fine.
    2. It will not run at all mame64.exe , i have used proc start and proc execute, I stated this earlier.
    3. WHen I use proc start, it gives failed to start immediately.
    4. If I use proc execute it just does nothing, no error message at all. Nothing.

  • Lifetime Qt Champion

    @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
    

  • Lifetime Qt Champion

    @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 run exe could you humour us by doing a QFileInfo on exe variable, as passed to start(), so that we can see it showing file exists?

    mame64.exe likely requires some DLLs to run, and may find them on PATH? Do we know that the PATH 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 the cmd report anything to your output redirections?

    Replace your attempt to run mame64.exe directly by a mame.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 running proc->start(exe); but you report QFileInfo fi(path+exe);. Please don't do that. I wrote

    on exe variable, as passed to start()

    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 your mame64.exe....



  • Before path and exe. Then use setworkingdirectory(path) of exe then proc start(exe).

    Now only path, full path to exe file. And no setworkingdirectory.

    It works. Obviously setworkingdirectory has a flaw somehow????

    THANK YOU. Sorry for shouting :)



  • @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 from C:? Try running a CD as the command and see what it reports? Run a DIR as the command and see what is in its current directory? I doubt there will be a flaw in Qt's setWorkingDirectory().

    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.



  • I know that the absolute path is (even after setworkingdirectory) still the project directory of the code as used by visual studio so I am not actually sure what setworkingdirectory should do. Only found that out by using qfileinfo. Thanks for that.



  • @jonndoe47
    I think QProcess::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 along PATH. 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 in C:\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 not mame64.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 to cmd. But, I assume that QProcess 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 call cmd and hand over the batch file (for calling cmd correctly see one of the posts above).



  • @SimonSchroeder
    You are right (unless it has changed in a Qt version), you must run a .bat via cmd /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-1

    process.start("del /s *.txt");
    process.start("dir \"My Documents\"");
    

    del & dir are cmd-builtins, not external .exes. Therefore they should not be executable without cmd /c, just like for a .bat file? Are you able to test whether these actually work from Qt under Windows?


  • Moderators

    @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.


Log in to reply