On windows is it possible to get dll's to look for dependencies in another folder without using the PATH environment variable? - c++

On linux I am able to set theRPATH of a shared library to $ORIGIN:$ORIGIN../lib. This tells the DLL to look in the same directory as the shared library as well as in the ../lib folder. I've read that on windows you just add the absolute path to ../lib (for example) to the PATH. Is there an alternative to this method? I want my dll to look in the ../lib folder but don't really want it on the path. Is this possible?

If the main DLL dynamic/delay-loads the dependent DLLs, it can call SetDllDirectory() (or better, AddDllDirectory()) before loading them.
If the main DLL static-links to the dependent DLLs, but the EXE dynamic/delay-loads the main DLL, then the EXE can call (Add|Set)DllDirectory() before loading the main DLL.
Otherwise, you will have to either:
update the %PATH% environment variable.
use an application manifest that specifies the paths of the dependent DLLs.
use DLL Redirection.

Related

How to include dll as relative path?

I have a dll in my project which I am referring through absolute path(C:\test\something\abc.dll) to load in my project. How do load it relatively or is there is better way to include it in visual studio project?
MSDN::
Before the system searches for a DLL, it checks the following:
If a DLL with the same module name is already loaded in memory, the system
uses the loaded DLL, no matter which directory it is in. The system
does not search for the DLL.
If the DLL is on the list of known DLLs
for the version of Windows on which the application is running, the
system uses its copy of the known DLL (and the known DLL's dependent
DLLs, if any). The system does not search for the DLL. For a list of
known DLLs on the current system, see the following registry key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session
Manager\KnownDLLs.
The standard searching order for Dlls is::
The directory from which the application loaded.
The current directory.
The system directory.
The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory.
The directories that are listed in the PATH environment variable.
You can always have your Dll with the application in the same directory. Carrying it as resource within application is not advisable.
You can specify dll name without path and place the dll in the same directory where the executable loading it resides, or in the current directory (the one from which you launch the program).

C++ Moving DLL out of root directory into a subfolder, visual studio

I'm a beginner with building software using C++. In my project I link to DLLs and I keep them stored in the root folder. I do this because I want the project to be portable from one machine to another, and I also want the release builds to have dependence from installing things into system32 and what not.
The problem is all the DLLs in the root folder is messy, so I want to organize them into subfolders. But I can't do that because putting the DLL in a root subfolder instead of the root, you get errors. I think because the DLL is copied to the output at the wrong location, not where the exe is, but in a subfolder, just like the source structure. Am I right about that?
What is a solution that will allow me to have the project be still be copy-pastable/portable between machines?
Windows searches for DLLs in predefined locations (see Dynamic-Link Library Search Order). Subdirectories of the directory where the application resides are not part of the search order.
To implement your requirement, you will need to explicitly add the directories to the searched locations. This process consists of two steps:
Call AddDllDirectory for each directory you want searched, in addition to the default search locations on application startup.
By default, DLL imports are resolved prior to starting a process' primary thread. To allow your application to change the DLL search path, import resolution needs to be postponed. The easiest way to do this is by using the /DELAYLOAD (Delay Load Import) linker option (see Linker Support for Delay-Loaded DLLs for additional information).
While it is possible, to segregate DLLs into subdirectories, it is best to keep them all alongside the executable image.
If you put the DLLs into subfolders instead of keeping them in the same directory as the executable, you would either have to modify PATH environment variable in Windows to point to every subfolder, or use the DLLs in LoadLibrary+GetProcAddress way instead of linking them to the executable via import libs.

including library and dll into c++ project

I have a third party library (say, tp.lib) and the third party dll (say, tp.dll) which I need to use in my C++ project (my project makes a dll, lets call it my.dll).
I have included the library with the #pragma comment(lib, "libraryname") in the header file
and also included the path of the library file in the configurationproperties->linker->additional library directories in my C++ Visual Studio project.
The code compiles and links okay. but fails to execute. When I used depends to check if i am missing something, I observed that the tp.dll is not found. The tp.dll resides in the same library folder where the tp.lib resides.
What should I do so that tp.dll gets included to my.dll?
DLLs have a different search path. Quote below from docs:
With both implicit and explicit linking, Windows first searches for "known DLLs", such as Kernel32.dll and User32.dll. Windows then searches for the DLLs in the following sequence:
The directory where the executable module for the current process is located.
The current directory.
The Windows system directory. The GetSystemDirectory function retrieves the path of this directory.
The Windows directory. The GetWindowsDirectory function retrieves the path of this directory.
The directories listed in the PATH environment variable.
Note
The LIBPATH environment variable is not used.
The search path at runtime does not include the folder where you put the lib library, so putting the DLL with the lib is not enabling the OS to find it at runtime. You can add that to the path, or move the DLL. The list of search precedence is on MSDN.
You can't "include the dll into another dll". You need to either deploy them together, or put the dependency dll in a place where Windows will find it.

How can I automatically load DLLs from a subdirectory?

In Visual Studio, you create a .dll project and it creates a .dll and .lib files. You link statically to the .lib, and if the .dll is in the same folder as the .exe, everything works.
I suspect that everything would also work if the .dll was in System32 or any other PATH folder (confirm or correct, please).
But here's the question: I want my exe to find the .dll in ./DLLS/ folder, that is, if my exe is in ....../MyApp/MyApp.exe then it should look for the .dll in ...../MyApp/DLLS/MyDll.dll. I DO NOT want to include the DLLS folder in path. Is there any way I can do this?
Please note that I do not wish to use LoadLibrary explicitly, so I can't specify the path there.
Thanks in advance for any help.
Here is the default sequence which Win32 applications go through when looking for a DLL:
http://msdn.microsoft.com/en-us/library/7d83bc18(VS.80).aspx
So according to this, another approach might be to call SetCurrentDirectory or SetDllDirectory. But in order for this to work you have to use the Delay Loaded Library functionality (you specify that in Project Settings in Visual Studio). Delay loaded library means that the DLL is loaded only at the moment when the program needs it, not automatically at the programs' startup.
You could use SetDllDirectory for this. The loader will use the additional directory you specify when loading libraries. There can only be one additional directory, however, so you need to make sure that there aren't other calls to this at a later point in your application, otherwise the directory you specify will be ignored.
If that API does not allow relative directories (I'm not sure), you could always call GetModuleFileName with a NULL first parameter to get the file name of the currently executing program. With a little string manipulation, you can get the absolute path to your DLLs folder.

Infernal Libraries (aka DLL Hell)

In a Project of mine, I use a Delphi Application which dynamically loads a wrapper DLL (exporting C-Style functions) which in turn is statically link against a bunch of 3rd party DLLs.
It works fine on my test machines, but on my customers computer it failed to initialize with an error Message like "Couldn't find entrypoint _somefunction#4AKKZ in TMYlibrary.dll".
After some investigation with sysinternal's process monitor, I realized that Windows would look fror DLLs in windows/sytem32 first, so if a DLL named similar to my DLL was present in system32, windows would pick that one and try to find my function entry points in it - which would fail.
Do you know of a possiblity to change windows' DLL the searching behaviour?
Additional Information
[Update] The .exe file is located on the top level of the application's folder tree.
The Wrapper and the 3rd-party-DLLs ar e both located in the Subfolder /bin of my apps Folder
Dev platform is windows XP/7, using VS2008 for the dlll and Delphi 2010 for the application
I found another solution myself:
SetDllDirectory adds an additional search path to the list of locations to look at.
From http://msdn.microsoft.com/en-us/library/ms686203%28v=VS.85%29.aspx
After calling SetDllDirectory, the DLL search path is:
The directory from which the application loaded.
The directory specified by the lpPathName parameter.
The system directory. Use the GetSystemDirectory function to get the
path of this directory. The name of
this directory is System32.
The 16-bit system directory. There is no function that obtains the
path of this directory, but it is
searched. The name of this directory
is System.
The Windows directory. Use the GetWindowsDirectory function to get
the path of this directory.
The directories that are listed in the PATH environment variable.
(maybe i should do my googling before I post on SO ;)
Ship the DLL in your program's folder. (same as the exe file).
Then Windows should try your version first.