Details
-
Type:
Bug
-
Status:
Closed
-
Priority:
Major
-
Resolution: Fixed
-
Affects Version/s: None
-
Fix Version/s: 4.0.0
-
Component/s: Native launcher
-
Labels:None
-
Environment:WinXP Pro
-
Number of attachments :
Description
If you do not have a JRE installed, the launcher will never prompt you do download one or install one from a local directory even if the launcher.ini is setup correctly to do so. This is a problem with the QProcess:execute method of the Qt library. The problem is that the code that looks like:
if (QProcess::execute("java", QStringList("-version")) == 0)
{
javaExecPath = "java";
return true;
}
always succeeds even if there is no "java.exe" anywhere on the system. The cause of this is the implementation of QProcess::execute. It's implementation looks like:
int QProcess::execute(const QString &program, const QStringList &arguments)
{
QProcess process;
process.setReadChannelMode(QProcess::ForwardedChannels);
process.start(program, arguments);
process.waitForFinished(-1);
return process.exitCode();
}
The problem is that internally, the "start" method uses "CreateProcess" to create the process. Of course this will fail if the program does not exist. But the code never sets the "exitCode" member in this case; it still has the value 0. The cleanup code in "start' sets the "error" member in this case. But since the QProcess is created locally, this member cannot be queried.
I've fixed this problem locally by adding a 2 new methods to "launcher.cpp" that look like:
int Launcher::execute(const QString &program, const QStringList &arguments)
{
QProcess process;
process.setReadChannelMode(QProcess::ForwardedChannels);
process.start(program, arguments);
process.waitForFinished(-1);
int exitCode = process.exitCode();
if (process.error() == QProcess::FailedToStart)
{
exitCode = -1;
}
return exitCode;
}
int Launcher::execute(const QString &program, const QStringList &arguments)
{
QProcess process;
process.setReadChannelMode(QProcess::ForwardedChannels);
process.start(program,);
process.waitForFinished(-1);
int exitCode = process.exitCode();
if (process.error() == QProcess::FailedToStart)
{
exitCode = -1;
}
return exitCode;
}
and changed all references of QProcess::execute to "Launcher::execute". This works fine now. I can supply a patch.
But I would like to know how launcher.exe is built and linked. What compiler chain (MinGW? win32-g++?) Also, how was this linked as when I rebuild, this uses the Qt library with DLL's and now the exe relies on them as well as the mingw DLL.
Great report!
I do not have a Qt / MingW environment under hand, but here is how I built the last version:
I haven't checked with the latest version of Qt, but removing the MinGW DLL dependency was tricky. I wrote about it: http://home.izforge.com/index.php/2007/02/20/334-qt-static-linking-and-removing-the-mingw-dll-dependency, I hope it will help you!
Thanks for your work!
- get Qt with MingW embedded
- compile a static version of Qt (it is dynamic by default)
- compile the launcher
- strip it using either the 'strip' tool from the MinGW toolchain, or run UPX
I haven't checked with the latest version of Qt, but removing the MinGW DLL dependency was tricky. I wrote about it: http://home.izforge.com/index.php/2007/02/20/334-qt-static-linking-and-removing-the-mingw-dll-dependency, I hope it will help you! Thanks for your work!