Moving QtCore4.dll et al in a separate folder than application (.exe)
-
Hello,
I would like to move all the dll's (including Qt's and plugins) in subfolder of the folder where the binary executable resides. The question has been asked several times in this forum and elsewhere. I've tested different of these solutions: some of them don't work, others provide poor user experience, I'll detail them later.
First, why I want to put the dll's in a separate folder: for user experience, it's much cleaner to have in the application folder only the application and a DLL folder.
Having- QtCore4.dll
- QtGui4.dll
- libgcc_s_dw2-1.dll
- mingwm10.dll
- QtSvg4.dll
- QtXml4.dll
- plugin folders ...
in the same folder as the .exe is confusing for non-that geek users and looks poor compared to the Apple Application Bundle .app.
I would like to have the following folder structure
@- ApplicationFolder
- myapplication.exe
- Libraries/
- QtCore4.dll
- QtGui4.dll
- QtSvg.4.dll
- ...
@
and that when the application is run, the running location is ApplicationFolder.
What does not make it for me:
- compiling statically: because of LGPL restriction,
- modifying the Windows PATH: no installation procedure (I want the ApplicationFolder to be moved from one place to another; even running on a usb key),
Assuming the .exe is moved into the dll folder, the following are not acceptable too:
- creating a .bat with command "Libraries\myapplication.exe": very poor: opens a DOS window and cannot rename .bat in .exe
- creating a shortcut with command "%windir%\system32\cmd.exe /c start Libraries\myapplication.exe": the shortcut icon will have this terrible arrow in the lower left corner, it seems difficult to remove this arrow.
Would be great but was not able to make it:
- using Run-Time Dynamic Linking Windows API as the first instructions of the main{} through LoadLibrary()
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686944(v=vs.85).aspx
It seems that all methods should be manually linked to get function handle via GetProcAddress().
Do you know a robust manner to have all the DLLs (including Qt's) in a separate folder or using LoadLibrary()?
Thanks
-
bq. Assuming the .exe is moved into the dll folder, the following are not acceptable too:
How about simply create shortcut for your exe?
You can also create simple win32 MT(without VS dependencies) exe wich just calls SehllExecute or CreateProcess with your binary in dll path, no console window or whatever will be shown...
-
To create a shortcut, the target has to be specified through an absolute path which is annoying if the application folder is moved from one place to another or is located on a usb key. In addition, shortcuts have a "arrow" on the icon (I know I'm extremist ;-) ).
-
or try to use "SetDllDirectory":http://msdn.microsoft.com/en-us/library/ms686203(VS.85).aspx before creating QApplication
-
In the .pro it is defined:
@
DEFINES += _WIN32_WINNT=0x0501
@
and SetDllDirectory is only available for WIN32_WINNT >= 0x0502 (winbase.h). Vexation law is at work :-DI'll try this and also have to be sure that changing the define from 0x0501 -> 0x0502 won't impact other parts of the application.
-
Just tested the SetDllDirectory() and have the same message as if the QtCore4.dll was not found.
Thinking again about that, we'll have troubles with libgcc and mingw dll's because they would be needed before any call, isn't it?
-
Sure, you will need to provide all dependencies to the user... So if you compile it with gcc, libgcc should be deployed with your app, also if you use openssl you will need to deploy it libraries to the end computer.
Create launcher like portable firefox and other programs do and use "ShellExecute":http://msdn.microsoft.com/en-us/library/windows/desktop/bb776886(v=vs.85).aspx to start you exe file from dll folder.
-
[quote author="AcerExtensa" date="1355405495"]or try to use "SetDllDirectory":http://msdn.microsoft.com/en-us/library/ms686203(VS.85).aspx before creating QApplication[/quote]
This won't work, because the required DLL's are loaded when your EXE file going to startup (by the operating system loader), so that happens before your main() function even gets a chance to do anything! If required DLL's cannot be found, your EXE file won't even start. And thus it never gets a chance to call SetDllDirectory() ;-)
The Windows operating system will look for the required DLL's in the following locations:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx#search_order_for_desktop_applicationsBe aware that "The directory from which the application loaded" is the directory where EXE file resides, NOT the so-called "current directory". If at all, you could add the directory where the Qt DLL's are located to the PATH environment variable before you start the EXE file. But this method is not very reliable. I would not create software to depends on the PATH environment variable to contain a specific path!
Installing the Qt DLL's into the Windows directory or into the Windows "System" directory also is NOT recommended at all. That's because installing DLL's on a System-wide context leads to a problem commonly known as the "DLL Hell". It's better to give each application its own separate DLL's.
If you would like to load a DLL at runtime, you would need to this by NOT linking your application against the Qt .lib files (import libraries) but instead use LoadLibrary() plus GetProcAddress(). But given the enormous number of functions you are going to need from QtGui4.dll and QtCore4.dll, this will be big pain and very error prone. Not even sure this method works at all for DLL's that export classes rather than just functions...
After all, it is a common practice to put the DLL's into the same folder as the EXE file on the Windows platform (except maybe for Plug-in DLLs). If you think that looks "poor", so do 99% of all Windows applications.
The ultimate solution: Build your EXE file with the static Qt libraries, so it will NOT depend on any Qt DLL's :-)
-
You can probably do this with carefully crafted manifest files because these do kick in before Windows tries to load implicit dependencies, see: http://stackoverflow.com/questions/2100973/dll-redirection-using-manifests for example. However, it is a lot of fiddling about for precisely no gain. The user should not care what is in the program directory.