Pages

Sunday, May 8, 2011

Forcing DLLs into submission - Delay Loaded DLLs

When I wish to run Elpis outside of my IDE, the executable can be found in the debug directory...but it's likely that I won't find it in time for the holidays. There are far too many files exported to that directory!

Now, this wasn't an issue before, and by before I mean a year ago when I had less than 3 DLLs exported. I now have 19 dlls and for each of those DLLs, there are four more files associated to it: *.ilk, *.lib, *.pdb, and *.exp.
That's 76 files to look through for that damned exe! (Not including other debug exports, test project executables, folders, etc...)

The Deadend
Obviously, the solution is to separate the *.exe's from the DLLs. Oh, but wait... hold on a sec... I have a feeling this might not be so straight forward.

On application launch, Windows searches the following directories for the DLLs needed:
  1. The directory where the executable module for the current process is located.
  2. The current directory.
  3. The Windows system directory. The GetSystemDirectory function retrieves the path of this directory.
  4. The Windows directory. The GetWindowsDirectory function retrieves the path of this directory.
  5. The directories listed in the PATH environment variable.
Copy-Paste from MSDN

Ok, so I can't just set the DLL search directory without setting a path variable? Gross! I might have to use LoadLibrary and GetProcAddress for each of my functions/methods. That breaks my heart because Elpis has quite a few methods to export/import. How tedious.

So now what? I guess quitting is always an option, maybe give up my life as a programmer all-together and take up dancing as a strategic career move!

The Saving Grace(s)
As invigorating as that all sounds, I've found a convenient solution. The solution entered my life, and my dream to dance fluttered away.

SetDllDirectory

Obvious in its intention, SetDllDirectory allows you to set a relative or absolute path to search for Dlls (only one path can be set at a time).  So now, we could set the directory at runtime BUT, the DLLs are loaded long before even the main is reached.

Not a problem: A nice feature that was added to VC6 (so, not new) was the option to delay the loading of a DLL until it is first called. All you need to do to use delayed load is to configure the executable project a little bit.

Configs
On the executable project in Visual studio

Navigate to  Project Properties->Linker
1. Add Delayimp.lib; to "Additional Dependencies"
(This is library provided by Mr. Microsoft, and contains the functionality to delay loading)

2. Add all delayed DLLs to "Delay Loaded DLLs"

3. Make sure that nothing in the DLLs are touched until the SetDllDirectory is called (this includes instantiation of objects defined in the DLL)

And that is that. Elpis DLLs can now live wherever I want them too (within reason), as long as I let Elpis know where to find them.

No comments:

Post a Comment