0

I have a project which uses external assemblies, located in a /libs folder. When I build the project, I don't want to copy all these assemblies into the bin folder since they are already in the /libs ! So i set CopyLocal=false, but the compiler can't find these assemblies.

I've seen this related post but i'm completely lost with this GAC and all these C# details.

Can someone explain me why it's so complicated and not just for the compiler : if an assembly is referenced on path P, i load it on path P, and if copylocal=false, i don't add it to my build ?

fazega
  • 327
  • 2
  • 13
  • If you don't want to register assemblies with GAC or mess with file paths then do yourself a favor and leave them in the same folder as your executable. – hoodaticus Jul 21 '17 at 17:57
  • I'd rather mess with file paths ;) i want to understand how it's working – fazega Jul 21 '17 at 18:03
  • Then Derek has given you the answer you should accept. You can override the assembly resolution routine and find and load the DLL's at runtime yourself with C# code. – hoodaticus Jul 21 '17 at 18:05

2 Answers2

3

What if you wanted to share this program with someone else? You'd have to give them the bin folder and the lib folder and maybe they'd have to be at different levels in windows explorer ( to be able to find them ). When your program is running out of the bin folder it needs to know where to find the files that it needs to run. One of the easiest ways is to turn on copy local so it is copied to the bin folder. You could also look up "AssemblyResolve" but it is a bit complicated and I don't think you'd want to get into that.

Derek
  • 7,615
  • 5
  • 33
  • 58
  • Don't understand your point. If i need to give someone this program (which is the case actually), i'll give him the /libs and the .exe, and the .exe should find the assemblies if i tell him it's in ./libs. I don't understand the difference between putting it in /bin and putting it in /libs. – fazega Jul 21 '17 at 18:00
  • 2
    @FaZeGa "the .exe should find the assemblies" You have to code that. You've told the COMPILER where the assemblies are, but not the .exe. By default, the .exe will look in the GAC, in the current folder, do some more [probing](https://learn.microsoft.com/en-us/dotnet/framework/deployment/how-the-runtime-locates-assemblies) and then explode. – Guillaume CR Jul 21 '17 at 19:19
1

Typically, a bin folder is intended as the main component of your deployment package. In a very simple application deployment, everything a program needs exists in the bin folder. You could copy paste that folder anywhere and it would work. Of course, that won't happen if your external assembly isn't there.

You find that those assemblies shouldn't exist in 2 places on your development machine, and I understand why you don't like that. The reason CopyLocal is set to true by default is because the typical scenario I described above is worth the cost of having assemblies existing twice in a development machine. Typically, an application will exist on many times more client machines than development machines, so the simplicity of a single deployment folder is worth the cost of disk space on dev machines.

You said yourself that you would include the lib folder whenever you'd give your exe to someone else? Wouldn't it be simpler to just give the bin folder with everything in it?

In your original question, you mention the compiler can't find the assemblies, I think that's incorrect and I tested a similar situation. The compiler found the assembly, however when I tried executing the code, the runtime told me it couldn't find it. The compiler does not insert code to make the executable find assemblies in relative paths. You can find the detailed probing behavior of .Net external assemblies here. Your exe can't magically guess that the assembly is in a lib folder in the parent folder.

You can circumvent all this by coding your own assembly resolution, but unless you are starving for a few kilobytes of disk space, let Visual Studio do its thing.

Guillaume CR
  • 3,006
  • 1
  • 19
  • 31