1

Fairly simple question I'm hoping but I've not managed to find an answer yet on Google that works...

I'm working in a C# testing context, and am referencing a managed C++ DLL which then references normal C++ assemblies. When I try to run my test I get a FileNotFoundException that doesn't give me any details on the file it was unable to find.

System.IO.FileNotFoundException: The specified module could not be found. (Exception from HRESULT: 0x8007007E)

I've done some checking with ProcMon and found it's trying to load up one of the C++ DLL's but it's probing all the standard places (C:\Windows, C:\Windows\System etc..). Is there a way I can redirect this to include an additional folder where all our binaries are built to?

I'm guessing there's something on the AppDomain but I've not quite figured out which property to use, which will work.

Ian
  • 33,605
  • 26
  • 118
  • 198
  • Have you tried to go into the properties and set the C++ dll to copy local and or have you tried to GAC or add the reference to the .dll thru the designer..? – MethodMan Jan 03 '12 at 16:46
  • I can't change the C++ Dll and don't really want it in the GAC... sorry – Ian Jan 03 '12 at 16:52
  • I've seen this type of thing in deployments when the appropriate C++ runtime library is not installed. Are you able to load and execute the unmanaged C++ DLL(s) directly, i.e., from a native C++ application? – dgvid Jan 03 '12 at 17:17
  • 1
    You could pinvoke SetDllDirectory() – Hans Passant Jan 03 '12 at 17:31
  • @HansPassant : You should post that as an answer. It seems to have worked for the first hurdle :) Thanks – Ian Jan 04 '12 at 09:23
  • possible duplicate of [best solution to use a DLL/Driver?](http://stackoverflow.com/questions/2333434/best-solution-to-use-a-dll-driver) – Hans Passant Jan 04 '12 at 09:43
  • Hmm, similar answer but I think the question has some merit for others who are having a similar problem as it's easier to search for, especially if I include the full error message which I'll add in now. – Ian Jan 04 '12 at 12:38

2 Answers2

1

Simply add that path to the Path environment variable.

In Windows 7: Press the windows key, type 'environment', select Edit the system environment variables, select Environment variables... add path...

Programmatically: See this post.

But I think a more common approach is to copy the referenced DLLs to your output directory. Even if this requires more disk space, it guarantees that the referenced DLLs are always compatible with your C# application. If the DLLs change by a CVS update, and you don't rebuild your C# application, it will probably not start as expected.

Community
  • 1
  • 1
Matthias
  • 15,919
  • 5
  • 39
  • 84
  • Probably will work, but is it possible to do so via C# instead? I don't want to have to tell the entire Dev team to update their environment variables if possible... – Ian Jan 03 '12 at 16:51
  • @lan: edited post. Nevertheless I don't think this is the better solution. What if one developer has the dlls on `D:\yourpath` instead of `C:\yourpath`? – Matthias Jan 03 '12 at 16:53
  • Also this post is to change the environment variables... Thinking about it this may stuff up the duplicates of the items in the GAC already. – Ian Jan 03 '12 at 16:58
  • I've tried the latter, but unfortunately the testing output directory isn't probed, that's what I'm trying to fix. – Ian Jan 03 '12 at 17:03
1

As per Hans suggestions:

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetDllDirectory(string lpPathName);

SetDllDirectory(@"C:\SomeDir");
Ian
  • 33,605
  • 26
  • 118
  • 198