DLL reference not copying into project bin - c#

Project A references Project B, and Project B references an external DDL (restored using NuGet). The DLL should get copied into Project A's bin folder (along with Project B's DLL):
In my case, when running Project A, I get the following exception thrown:
Could not load file or assembly 'PostSharp, Version=3.2.18.0,
Culture=neutral, PublicKeyToken=b13fd38b8f9c99d7' or one of its
dependencies. The system cannot find the file specified.
The DLL is not being copied into Project A's bin. All other external references from Project B are being copied across just fine, which is what is confusing for me.
Copy Local is set to true for all references involved. Example:
How do I do this?
Note: Using Visual Studio 2013.

The options that I found were to:
Add a reference to PostSharp in Project A.
Add dummy code in Project B so that the compiler would detect that the reference is being used.
Add a build event to force copy the DLL.
I don't like any of the above solutions. They are hacks in my opinion and will only make for a more unmaintainable solution in the long run.
I have fixed the problem by using a common output directory. This seems to be a recommended solution by many. I have also experienced much faster build times. See this Stackoverflow post.

When I ran into this problem it was because I changed a project's name, but did not change the assembly name - it was identical to the assembly name of another project in the solution.

I've added some dummy (unused) code on Project B, making reference to the DLL needed.
Thus, the compiler will guess that it must copy the DLL into project A output.

Related

Visual Studio C# .dll vs. project referencing

I have two C# projects in my Visual Studio solution. Project B needs to reference code in Project A. Both projects need to be compiled to dll's and then used in an application.
In Project B I can set a reference to project A and that allows things to compile. But when I actually use the resulting dll's in my application it throws a missing assembly reference error.
My current solution is to tell Project B to reference the bin/debug/ProjectA.dll. Everything works when running the application with this configuration. But this solution has a number of problems. For instance, any code written in Project A that B relies on wont be visible to B until A has been rebuilt. And building the solution relies on A being built first.
Is there a way that I can add a reference to Project A but have the resulting dll built so it looks for the ProjectA.dll reference and not the project itself? I expect there is, but my google searching has resulted in no answers.
For instance, any code written in Project A that B relies on wont be visible to B until A has been rebuilt. And building the solution relies on A being built first.
This is not a problem, this is, in my view, a benefit. As you are guaranteed to not be able access functionality which is not there. In case of a new functionality, one may say, it's not a big deal: I can not find it, got an exception/error so I know something went wrong. But what about updated code ? In this way you are guaranteed that B will use only most updated version of A.
Is there a way that I can add a reference to ProjectA but have the resulting dll built so it looks for the ProjectA.dll reference and not the project itself?
You may simply implement post-build event on your project A which copies it and all dependent DLLs in some predefined central location, where B.dll will be copied too. If your B.dll depends on A.dll, OS, following default behavior, will search for A.dll in the same folder where B.dll is, for first, before checking %PATH% variable content.

One of the assembly gets deleted from my solution everytime I build

I am using VS2012 and I am seeing weird problem. I added a new project into my solution and that project was working all fine until now.
Now, Everytime I build/re-build the solution, i am seeing reference errors from different projects which are using that particular reference. I checked the bin/debug folder and assembly is not there.
Surprisingly enough, when I build that particular project by it self, it builds successfully and produces the assembly into bin/debug folder.
Now, it works when built alone but does not work when build in solution. And when I build entire solution, something causes the .dll file to be deleted somehow to cause all the references to break.
I have done following things so far:
Made sure this project is second one to be built in entire solution
Went through all the projects which I are depending on this project and added the dependency manually.
Any ideas on how can I solve this issue?
If the referencing project and the referenced project are both in the same Visual Studio solution then it is generally considered a best practice to use project references rather than assembly references. This ensures that build dependency orders are maintained automatically and helps prevent you from accidentally creating circular references.
Assembly references should only be used when you cannot add the project that created the assembly to your solution. When you do use assembly references (which I don't recommend in this case) you should put the assemblies into a common folder outside of your bin\debug folder structure to ensure you don't accidentally delete the file when, for example, you do a Clean operation.

Difference Between DLL Reference's? And Uses?

Please any one explain this. This Question helps to understand common things
Question:
What is the difference between when you 'add DLL reference from one project to another project via Browse Option and Add DLL reference from Solution project to another project and copy-paste from one project to another project'?
I have found an answer on google
Answer:
Adding a project reference adds a local project's DLL to the project that references it, and every time the solution compiles, the updated DLL for that project gets copied to the other project. So when you go through the build process, if you have 5 projects, each one rebuilds its DLL, and copies that DLL to its references.
But:
I don't know what the process is and the difference when we copy-paste from one project to another project?
When you do copy paste from One project to another, the dependent project add its reference of the file that you have paste in the project solution directory
When you do copy paste the dll of one project to the other project's directory and then Add its reference by browsing to that directory where you have pasted your dll. Then VS only add its reference and copy that dll to its bin folder and show you (allows you) all the method and properties that it contains.
If you do any change in your source project solution like adding or modifying methods then the updated dll of that project is not available in your dependent project solution.
So VS still points to the old dll file just because of the reference you added. So whenever you made any change in your source project solution, you have to add the reference of the updated dll to your dependent solution every time.
In Second Case: When you add reference of your source project into your dependent project solution, VS always take the most recent updated dll from your source project into your dependent project. So in this way you don't need to add reference every time you compile the code or debug.
When you just reference a DLL by browsing to it, VS would copy it to the output directory of the dependent project.
Suppose afterwards that DLL is updated - there is no guaranty that VS would retake that updated DLL, and copy it again to the output directory of the dependent project - which mean, that even after you fixed some bugs in the other project, those bug would persist in the dependent project (because it is still using the previous version of that DLL).
When you add reference to other project in the solution, VS would always take the most recent and updated DLL outputted from that project.

How to remove duplicate reference assembly for multi-project solutions in Visual Studio?

Well, I'm not familiar with C#. Here's my story:
In the VS2010 solution, there are 2 projects: Entrance, Core and Plugin. Entrance may be compiled into an exe, while the others may produce dlls. Core is added to Entrance's and Plugin's reference. Plugin is set to be compiled to plugin folder. So after compiling, the output directory contains:
entrance.exe
core.dll
plugin\core.dll
plugin\plugin.dll
How can I remove the duplicate core.dll under plugin? Thanks.
In the Solution view of the plugin project, right-click on the core.dll reference and select Properties. Set Copy Local to false to prohibit copying of the assembly to the output directory. Note this will only work properly at runtime if the referenced assembly can be found by the application. In your case it's fine since core.dll is also referenced my the application but that might not always be so.

References from class library are not copied to running project bin folder

I have a class library that represents my logic layer. To that library I've added a nuget package for Google.Apis.Analytics.v3 - it installed the package and all it's dependencies.
I have a console application that uses that logic class library (regular reference). everything is written and compiled fine.
The problem is that during runtime it threw an exception that Google.Apis.dll wasn't found. This DLL is a dependency that was downloaded with the nuget.
Checking the BIN folders, I've found that in the class library bin folder this DLL was present, but in the console application BIN folder it wasn't (while other related DLLs were). So this means that the not all references where copied during compilation.
I've searched online, and found all kind of workarounds that didn't really work (like manually editing the project file and removing a true xml line on that dll definition).
What I ended up doing is adding the same nuget library to my console application - it works but feels a little dirty and not the way it should be. I think the console app is the client who's supposed to get it's services from that logic class library which should know it's stuff without the "client" worrying about it.
Also, that console app is not the only one who's gonna use that service, I'm also planning on a web app that will use that functionality - so I will need to add the same nuget to that web app as well - again, feels a little messy...
Is it just me? is that the right way to go about it? I was thinking about writing a WCF project to handle that functionality - but that seems a little of a overhead for just on functionality, and probably slow my workflow down just to keep things "cleaner" in my opinion.
Am I just over-thinking it?
Thank
Explanation
For a sample scenario let's say we have project X, assembly A, and assembly B. Assembly A references assembly B, so project X includes a reference to both A and B. Also, project X includes code that references assembly A (e.g. A.SomeFunction()). Now, you create a new project Y which references project X.
So the dependency chain looks like this: Y => X => A => B
Visual Studio / MSBuild tries to be smart and only bring references over into project Y that it detects as being required by project X; it does this to avoid reference pollution in project Y. The problem is, since project X doesn't actually contain any code that explicitly uses assembly B (e.g. B.SomeFunction()), VS/MSBuild doesn't detect that B is required by X, and thus doesn't copy it over into project Y's bin directory; it only copies the X and A assemblies.
Solution
You have two options to solve this problem, both of which will result in assembly B being copied to project Y's bin directory:
Add a reference to assembly B in project Y.
Add dummy code to a file in project X that uses assembly B.
Personally I prefer option 2 for a couple reasons.
If you add another project in the future that references project X, you won't have to remember to also include a reference to assembly B (like you would have to do with option 1).
You can have explicit comments saying why the dummy code needs to be there and not to remove it. So if somebody does delete the code by accident (say with a refactor tool that looks for unused code), you can easily see from source control that the code is required and to restore it. If you use option 1 and somebody uses a refactor tool to clean up unused references, you don't have any comments; you will just see that a reference was removed from the .csproj file.
Here is a sample of the "dummy code" that I typically add when I encounter this situation.
// DO NOT DELETE THIS CODE UNLESS WE NO LONGER REQUIRE ASSEMBLY A!!!
private void DummyFunctionToMakeSureReferencesGetCopiedProperly_DO_NOT_DELETE_THIS_CODE()
{
// Assembly A is used by this file, and that assembly depends on assembly B,
// but this project does not have any code that explicitly references assembly B. Therefore, when another project references
// this project, this project's assembly and the assembly A get copied to the project's bin directory, but not
// assembly B. So in order to get the required assembly B copied over, we add some dummy code here (that never
// gets called) that references assembly B; this will flag VS/MSBuild to copy the required assembly B over as well.
var dummyType = typeof(B.SomeClass);
Console.WriteLine(dummyType.FullName);
}
If you have the following dependency chain:
Lib1 <-- Lib2 <-- MyApp
TLDR version: by not making assumptions, the build system avoids introducing uncertainty/unexpected behavior.
When you build MyApp, Lib2 will get copied to MyApp's bin directory for you, but Lib1 will not. You will need to add a reference to Lib2 and Lib1 in MyApp in order to get Lib1's dlls in MyApp's bin directory (otherwise you'll get the runtime error). It would be impossible (or maybe just really difficult) to identify the exact set of files that end up in Lib2's bin directory that would be safe & appropriate to copy over to MyApp's. If the build system made assumptions that everything in Lib2's bin directory was safe for MyApp, or if it implicitly referenced Lib1 for you, it could change the behavior of MyApp unintentionally.
Imagine a solution where more than 1 project depends on Lib2 but one of those projects wants to load an adjacent .dll file using Assembly.LoadFrom/Activator.CreateInstance/MEF/etc. (a plugin) and the other one does not. An automatic copy operation could grab Lib2 along with the plugin dll and copy it over to the first and the second project's build directory (since it's in the Lib2's bin directory as a result of a build operation). This would change the behavior of the second app.
Alternatively, if it was a little smarter and implicitly referenced Lib1 for you when you referenced Lib2 (and didn't just copy bin directory contents), it could still cause unintended consequences. What if MyApp already depended on Lib1, but it was using a GAC'd/ngen'd copy that was compatible with the one that Lib2 requires. If adding a reference to Lib2 implicitly created a reference to Lib1 for you, that could change which Lib1 got loaded and change the runtime behavior of your application. It could maybe detect that there already is a Lib1 in MyApp's bin directory and skip it, but then it would be making assumptions that the Lib1 that's already there is the right one. Maybe it's a stale .dll waiting to get wiped away by a Clean operation and the overwrite was the right move.
NuGet addresses the problem you're describing with package dependencies. If Lib1 and Lib2 both had nuget packages and the Lib2 package depended on the Lib1 package, when you add Lib2 to MyApp, Lib1 would get added as well. Both pacakges' dlls would end up in MyApp's bin directory.
The best thing to do is invert your thinking a little bit. Instead of thinking:
Lib2 needs a reference to Lib1 in order to compile so I'll add a reference to Lib1
Think:
MyApp needs Lib2. Whatever Lib2 needs, I need. So MyApp & Lib2 both get a reference to Lib1.
If you have 10's of dlls it's easier to do a copy with a postbuild event:
xcopy "$(ProjectDir)bin\*.dll" $(SolutionDir)MyTargetProject\bin\" /y

Categories