1

I have a C# project, a class library, wich is a module for another project, and it's output path is in a subfolder within the main-projects output path (i.e. outputpath = C:\WHATEVER\MainProject\Modules.

In this Project, i reference a library (let's call it a.dll). this in itself works fine, but this a.dll needs other libraries at runtime to work (let's call them b.dll and c.dll). I added these two files via Add -> Existing Item, and set "Copy to Output Directory" to "Copy always" for b.dll and c.dll.

When i build the project, all three dlls are copied over into the output-path of the project (as expected), but a.dll can't seem to find them. As soon as i copy b.dll and c.dll into the main-projects folder (where the .exe is) a.dll can suddenly find them.

I don't want to have b.dll and c.dll in the main-projects folder, because they are only part of the module i'm currently developing, and not the main-project itself. How (in Visual Studio 2015) do i tell a.dll where to look for b.dll and c.dll? I tried adding the probing-part in the appconfig (as suggested here: Reference a DLL from another DLL), but that had no effect. I do not have the sourcecode for a.dll.

Community
  • 1
  • 1
Neutrosider
  • 562
  • 3
  • 12

1 Answers1

1

The first part of this answer is based on what can be found here: https://stackoverflow.com/a/1892515/937093

The method being used is basically the same as the one referenced in what you linked, but instead of using the XAML method, it uses the C#/code method (easier to debug/figure out what is going on).

Add your custom path as described in that answer. Do that in the Main method of your application. Start by adding the relative path to that folder, if that doesn't work, take a look here: explanation of fuslogvw, to figure out where your program is looking, maybe a path is wrong or you don't have permission to look into that specific directory.

If all fails and/or you are getting nowhere here, you can also try the following:

In C#/.NET you've an event AppDomain.CurrentDomain.AssemblyResolve, you can read about it here.

In short, that even fires if .NET can't find an assembly and the eventhandler of that event allows you to resolve an assembly for .NET.

Inside the event you could do something like this: AssemblyName reqAssemblyName = new AssemblyName(args.Name);

if (reqAssemblyName.Name.ToLowerInvariant() == "b")
{
    return Assembly.LoadFrom(pathToAssemblyB);
}
else if (reqAssemblyName.Name.ToLowerInvariant() == "c")
{
    return Assembly.LoadFrom(pathToAssemblyC);
}
else
{
   return null;
}

To get the path to the two assemblies you can use Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "mysubfolder","b.dll");

Community
  • 1
  • 1
Steffen Winkler
  • 2,805
  • 2
  • 35
  • 58
  • I tried your first answer. It's not saying that it can't find the dll anymore, but within a.dll itself an exception is thrown. Is it possible, that a.dll is developed in a way, that makes it impossible for a.dll to work with b.dll and c.dll if they're not in the MainProjects path? – Neutrosider Feb 10 '16 at 13:52
  • I don't think that's possible. Maybe c or d.dll need another reference? In any case, you should probably try to get more informations about that exception inside a.dll. Maybe enable `Common Language Runtime Exception` in the `Exception settings window`, more details about that [here](https://msdn.microsoft.com/de-de/library/x85tt0dd.aspx). If the exception is thrown, dig into it to figure out what it complains about exactly. Check `Message`, `StackTrace` and `InnerException` (can be recursive, as an Exception can have an `InnerException` which again is an Exception) – Steffen Winkler Feb 10 '16 at 14:01
  • I don't think that b.dll and c.dll need another reference, because when they are in the MainProjects folder, i don't get any Exception, and the library works. Sadly, the thrown exception is a custom exception. It just says "OBID.FeMlcException: Error in Module FEDM: The transferred pointer is NULL". i currently cant use the debugger, only log exceptions to a file, because i can't build the MainProject at the moment. – Neutrosider Feb 10 '16 at 14:08
  • `The transferred pointer is NULL` that sounds like something a C/C++ dll would say. Are you sure that b.dll and c.dll are .NET dlls? – Steffen Winkler Feb 10 '16 at 14:38
  • I'm pretty sure they're C++ libraries. But as i never directly interact with them (only with a.dll), i thought that made no difference – Neutrosider Feb 10 '16 at 14:40
  • 1
    that makes kind of a big difference. For example the 2nd approach I posted above would not work with a C++ dll. You should definetly fire up FuslogVW. I'm pretty sure it logs C++ references as well. Oh also if it's a COM dll you need to run regsvr32 against the dll inside the subfolder and not just against the dll in the basefolder. – Steffen Winkler Feb 10 '16 at 14:46
  • I've never heard of fuslogvw (i need to learn more about working with libraries ^^). I'll look into it. – Neutrosider Feb 10 '16 at 15:09
  • @Neutrosider it's a tool, linked in my answer. Basically, once enabled, it protocols every try to load a dll from a .NET program. Don't forget to disable it when you're done. – Steffen Winkler Feb 10 '16 at 15:13
  • Ok, i used fuslogVW, but the result is strange. the loaded .dll files are exactly the same, no matter if they are in the MainProject-root or in the Libs folder (as long as i use AppendPrivatePath). fuslogVW showed me, that when the dll's are not in the MainProject folder, they do get loaded successfully from the Libs folder. Therefore I don't understand, why it's not working, when the DLLs are not in the MainProject-folder – Neutrosider Feb 10 '16 at 15:46
  • @Neutrosider that's interesting indeed. If those are 3rd party libraries you should probably try to get in touch with whoever provided those. Maybe they've an idea what's going on or they know how to get more detailed logfiles or any logfiles at all. If they're in-house, find the guy that wrote them and ask him about it. On the bright side: The assemblies are being loaded now, that's something, right? ;) – Steffen Winkler Feb 10 '16 at 15:51
  • they are, therefore the question i asked is technically answered, and on top i learned something ^^ – Neutrosider Feb 10 '16 at 15:54
  • i feel kinda stupid right now. I got it 100% working now, by simply setting the current working-directory. that's all i deeded to do ^^ – Neutrosider Feb 11 '16 at 12:45
  • @Neutrosider ah, ok. Did you use the `Process` object to set the working directory? – Steffen Winkler Feb 12 '16 at 10:41
  • 1
    i didn't. Should i have done that? This is all i did, to make all the dlls work while not in the project-root: `System.IO.Directory.SetCurrentDirectory("Modules\\EDoor\\Libs");` – Neutrosider Feb 12 '16 at 11:30
  • @Neutrosider nah, I was just curious because the only 'workingdirectory' property I know about is the one on the `process` class. Was just curious about what exactly you had to do. Thank you :) – Steffen Winkler Feb 12 '16 at 12:20