2

My application implements a plugin architecture of sorts, using LoadLibrary, GetProcAddress and FreeLibrary. Since all my dlls are in the same directory as the executable, when I look for a dll, I get the executable's directory and search there, using this function:

string FileSystem::GetPathToProgramDirectory(){
    char progname[MAX_PATH];
    GetModuleFileNameA( NULL, progname, MAX_PATH );
    PathRemoveFileSpecA( progname );
    return string( progname );
}

This works on production, but when I try to run this under an integration test using NUnit, the executable directory ends up being NUnit's, and so loading fails. Bear in mind, this is unmanaged C++; in managed C++ I solved this using Path::GetDirectoryName(Assembly::GetExecutingAssembly()->Location), which works in both cases, but the unmanaged case got me stumped. Is there an unmanaged Winapi equivalent for that?

dario_ramos
  • 7,118
  • 9
  • 61
  • 108

1 Answers1

2

The problem here is that GetModuleFileName with a NULL first parameter gives you the path of the executable file currently running the code, while you want the specific module that's running the code. So, when you run your code under NUnit, you end up with the test harness executable instead of what you expected.

What you really want is to get the handle of the currently executing module and then pass that to GetModuleFileName. This StackOverflow post details a number of ways to get the handle of the currently executing module.

Combine the current module handle with the code you currently have, and this should all work under NUnit.

Community
  • 1
  • 1
Chris Schmich
  • 29,128
  • 5
  • 77
  • 94
  • 3
    I'd always prefer to remember the module handle when it is passed to the DLL in `DllMain`. – David Heffernan Jan 16 '12 at 19:41
  • @David: good point, I'm surprised that's not mentioned in that SO post, either. For @dario_ramos: look at your `DllMain` entry point (http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx) where the first parameter is the handle to your DLL. – Chris Schmich Jan 16 '12 at 19:44
  • @dario_ramos: I might misunderstand what you're saying. Here's my recap: you have some code (the code in your question) that lives in some DLL that controls/manages plugins that are implemented in other DLLs that live in some directory relative to the controller/manager DLL. If that's the case, you can get the handle to the controller/manager DLL (via the SO post I linked to, or via David's method), get the full path to it via GetModuleFileName, and then do whatever manipulation you need to get to your plugin directory... – Chris Schmich Jan 16 '12 at 19:57
  • @dario_ramos: ...(continued) If you use David's method, you just need to add or modify your controller/manager DLL's DllMain method to store the first parameter (the DLL module handle). Then, when you need to find the plugin directory, you can use this module handle to get the full path to the plugin directory. – Chris Schmich Jan 16 '12 at 19:58
  • I just figured that out myself (that's why I deleted my comment). I'm kinda sleepy :P The solutions from the post seem more reusable (don't force clients to implement DllMain), but the DllMain solution avoids asking for the HMODULE twice... So I'm thinking which one should I use, but no doubts now beyond that. – dario_ramos Jan 16 '12 at 20:04