I've always taught myself and others to think of the bin folder as being transient.
That is you should be able to delete it and next time you rebuild it gets recreated and any references get copied into it without any hassle And not to put your eggs all in one basket. Or in this case don't put all your required dlls directly into the bin folder. Have them elsewhere and just reference them.
I've seen people falling down when they put dlls directly into the bin folder and reference them there. So I try to avoid this and put all my required dlls in a folder called Refs and add references to the dlls in there. At compile time they will get copied into the bin folder anyway.
Am I insane? Is this being too careful? common sense?
What is best practice in this scenario?
Cheers,
-- Lee
UPDATE : Turns out i'm not mad
Cheers guys you've picked up on some points I forgot to mention.
Mainly :
Not checking the bin folder into source control
That's right, you don't want to put referenced dlls in the bin folder. If you are using version control, bin and obj folders should always be completely excluded.
All referenced dlls should be included under version control, preferably in a separate subdirectory under your project's trunk, so that everyone has all necessary sources and references for each clean rebuild. bin folder must easily be recreated from scratch.
That's something that I believe most people will expect when checking out your source.
We also include a _READ_ME.txt file in the root of the project, stating additional info on tools and stuff needed to batch-build the project (nant, perl, etc.), so there may be some specific differences from time to time, but never surprises of this kind.
No this makes complete sense and is a practice I myself implement on personal projects. Anything under the bin folder should be treated as property of the msbuild / Visual Studio environment.
While they both take great care to only delete the outputs they know about, it's possible for the user to not fully understand what is the build output and copy over a build output and consequently have it deleted during a "Clean" style operation. It's also possible for other tools to be more aggressive here in cleaning out DLL's. I myself tend to nuke the bin directory from time to time if I think the build process is looking at stale data.
Additionally having a ref's location gives you a single place to update references for a collection of projects within a solution. For me it's a very natural construct.
I think of the bin folder as being transient, it is a place for the full working compiled application to go.
We place any external Assemblies in a directory called Assemblies. Many others use a directory called lib. This separates idea of something that is needed to compile the application from the compiled application itself.
I have no idea if you're insane, but we followed the same practices at the last place I worked and I've carried them over to my own work. The /bin and /obj folders are outside version control and something I never touch. They basically don't exist as far as I'm concerned during development. All included DLLs sit in another folder and are referenced.
Related
I have 3 projects in my solution and a bunch of 3rd party or company dlls. Each time I rebuild my project or clean solution, a lot of this dll's are deleted, therefore missing. It is pretty annoying to reference this dll files again and again after rebuilding. Can someone explain how to avoid this? Thanks in advance.
The bin folder is just the binary output from a build, so when you clean your solution, all the assemblies in the bin folder get deleted. You should reference the assemblies from some other location. One suggestion is to create a Shared Resources folder within your project, copy your assemblies to that folder, then reference them from that folder. This way they won't get deleted from bin on a clean/rebuild and Visual Studio will copy them there as needed.
Right-click on the References folder in your project and choose Add Reference...
Use the browse functionality to locate the assemblies you want to reference (don't worry about manually copying them to/from your bin folder)
After the reference is added, right-click on the reference in your references list and choose Properties
Make sure the Copy Local property is set to True
This will ensure that assembly is copied to your bin folder on every build.
In my case, .net framework version is the problem. I had to lower its version to 4.5 and then the projects got built properly and able to reference in other projects
As Troy explained in his answer, indeed a reference to a *.dll file, kept outside the bin folder, ensures that the dll file does not get definitively wiped out when cleanning the project.
However, just by adding a reference to the assembly might not be enough. For instance it would not work for some other file types, such as the *.pdb files as well as for the *.resources.dll files (which are typically spread in many sub-folders named after the language codes (2 letters' language code)
To depict this problem with a real life situation, I picked up an assembly for which the source code is either gone, or not compatible anymore, etc. I chose (on purpose...) a 13 years old AjaxControlToolkit composed of many component files. The picture below illustrate its composition. Every time the "Clean" command is applied to the project all these files are deleted, except the one which is the referenced assembly. Moreover having several *.resources.dll file assemblies of the same name, as in the present case, makes it inconvenient, if not possible, to add "references" to each of them from within the same project.
Nevertheless here is a pretty simple workaround:
keep this file hierarchy in a separate folder (as Troy explained in his answer)
just copy them over in the bin folder using a command line entered in the Pre-build event of the project, such as xcopy "$(SolutionDir)AjaxControlToolkit" "$(TargetDir)" /y /i /s /r /q
Hoping that will be useful to someone...
I have some c# projects. I added post build event to those projects that copy the resulted assembly (dll) from the bin into common folder.
It appears that each compile generates assembly which is binary different from the previous even when I don't modify the project files.
It is quite a problem for me since I'm using Kiln that monitor those file and think they were modified.
I read somewhere that the dll stores time stamp of compilation which if true then I cannot fix this. If so how do you manage your shared DLL in such a way that your repository (Git/HG) doesn't commit all your compiled projects that weren't modified?
Thanks,
Eran.
To address the specific question of "How do you manage your shared DLL in such a way that your repository (Git/HG) doesn't commit all your compiled projects that weren't modified?", I have a very simple answer: ignore.
We exclude /bin and /obj from the directories which our source control will even attempt to commit. This does mean that you will need to recompile the code on each machine after each change, but Visual Studio would do that anyway for any project where the code has changed.
Don't commit the output folders of your projects.
If you want to have a Setup folder or something similar that always contains the latest versions of the assemblies created by your projects, the solution is to make sure that your post-build event is configured to run only when the build updates the project output. There is an option that is named like this:
during development of our application we use a branching structure and while we are developing another team is using earlier builds of our software to create content with it.
To facilitate easy swapping between builds and teams I was hoping to use empty Hintpaths in the content projects' csproj files so that they can use our GAC installed assemblies to build against and in the meantime add a reference path to the projects for our use during development and test cycles where we don't want any assemblies installed in the GAC.
However, it seems reference paths are not stored in the csproj file and thus don't get sourcecontrolled. Since there will be extensive branching it would be less than ideal to have to set all reference paths again when a developer pulls another branch from sourcecontrol.
I've been searching for a bit now and can't seem to find ways to do this. Anybody know of a way to force the reference path in and out of sourcecontrol?
We're talking Visual Studio 2008 and TFS 2008 here.
Cheers,
Anton.
Ok, I seem to be a little clearer in the head after a good night's sleep, took the logical step, namely investigate where exactly the information was stored and how. It turned out the information was stored in the .user file for the project in the project's folder and as it turens out this file contains mbsuild xml.
I then did what I wanted as follows:
Create the Reference path as I required it to facilitate both scenarios without any work.
Browse to the Project's .user file
Copy the PropertyGroup containing the ReferencePath
Paste the PropertyGroup in all the necessary Projects' .csproj xml.
Reload and build.
Done.
The references are stored in the *.csproj file. The nodes are ItemGroup/Reference...
Thomas
This is pretty simple--we do this in our shop.
First, in the Workspace (using Windows Explorer, browse to the Solution folder), create a folder. We name it "Referenced Assemblies". In here, drop all your DLLs.
Now, in the Solution, add a new folder to match the one created in Windows Explorer. Into that folder, add all the DLLs you just dropped in.
Finally, in each project, set up your references to use the DLLs that were added to the solution.
Now your project references DLLs that are part of the solution, so that when the build runs, it will grab the DLL from Source Control to generate the build.
Also, I'd recommend not using the GAC at all if you can avoid it. In my experience, reference behavior is strange. It seems references go first to the GAC, then to the DLL in the local folder, meaning that if the DLL is updated, the one in the GAC is used instead of the DLL in the local folder (which is likely the updated one).
I've got a C# project in visual studio that is building a DLL, and another console project which includes the first as a reference. These are both in the same solution.
The trouble is when I add methods to the DLL, then rebuild the console project doesn't seem to pick them up.
For example, in the DLL I have a class Converters. If I add a method
public static void test() {}
it just doesnt' show up in the console app at all. Intellisense doesn't autocomplete it, and if I manually type it in it gives a compiler error.
If I go in and delete the dll files then rebuild that works (or better yet, delete the bin and obj directories) but that seems rather drastic.
I'm sure this is a basic error, but I can't seem to find the solution after some googling.
How are you adding the reference? As a project reference or by browsing to the DLL? If you're using the latter then it will copy it locally to the bin directory of your console app and won't refresh it unless you manually delete it. If you add it as a project reference it will copy it as and when it needs to.
The exact thing happened to me once on a project - it turned out the build command wasn't configured to build these DLLs.
Check Build - Configuration Manager, and make sure the project is checked:
(Image from msdb - Setting the Build Configuration)
close Project visualStudio and
rebuild again your dll (other project visualStudio)
One of the things to note is the Target Framework of the Projects, if you compile your Project A with target framework different then that of Project B and it is referencing the dlls of Project A you may run into this kind of trouble. So, make sure that the target framework for both Projects is same.
Check that you don't have the ddl inside the bin folder of your project. Whilst I was adding the reference by browsing for the dll, I had forgotten that I manually copy pasted a version into that folder. No matter how many times I cleaned and rebuilt, it didn't seem to update.
Deleting that dll and re-referencing fixed the issue.
Change the reference to the dll to the Project, instead of the output.
This is certainly unexpected behavior. It sounds like the reference between the two projects is broken in some way. Two issues come to mind.
Possible problem with the reference. Try deleting the reference in solution explorer and readding the reference and seeing if that fixes things. When you re-add make sure it's a project reference and not a file reference.
It's possible that the time stamps on the files in your project are off. See if they are in the future.
check the folder which contains the reference. does it contain a refresh file with a relative path in it? if so, and if assembly names in the location pointed to by the relative path are common with those in of (project) references which should auto update, then these references no longer auto update! what you end up is a static reference to the assemblies present in the relative path contained in the refresh file.
you may also have to delete the projectreferences key in the sln file and add references afresh
I hate to beat a dead SO question but 8 years after the original question and none of the above solving the issue for me, my problem was in VS2013, but to solve it I simply removed and re-added the reference to the DLL in the project that invokes it.
I hope this helps some people in the newer VS realm having the same issue.
I found out that build time of C# solution with many projects gets much faster if you don't have "copy local" enabled everywhere. I did some tests and it seems that (for our solution at least) we could increase build time by factor 2-3 just by removing "Copy local". This probably means we have to store libraries in some common directory.
Any suggestion/best practices how to acheive this? Note that I would like to keep references to projects, not to DLLs.
We retarget the output directory of projects to be ../../Debug (or ../../Release)
Our libs are placed in these directories as well.
We set the reference paths in each project to be the Debug or Release directory accordingly (this setting is persisted in the user files since it is an absolute rather than relative reference)
We keep project references as project references, All dll references have copy local false and specific version false unless they are system level dlls we know will be in the GAC on all deployed machines.
This works a treat and manual builds in the IDE mimic scripted builds from the command line (using MSBuild)
Test projects not for deployment do not direct their output to the centralized Debug|Release directory, they just use the standard default location (and do use copy local to avoid issues with locking)
The library versions may be changed by the automated build process replacing the dlls in the Debug and Release directories.
I recommend building to ..\..\Build if your application is spread across solutions. (If you only have one solution, you may consider ..\Build.) Visual studio will, by default, pick up reference files in it's output folder. When building without VS using MSBuild, though, you must add the build folder as a reference path as shown in the example below:
<Target Name="BuildApp">
<MSBuild
Projects="#(ProjectReference)"
Targets="Rebuild"
Properties="ReferencePath=..\..\Build;$(LibraryFolder)" >
</MSBuild>
<OnError ExecuteTargets="BuildFailed" />
</Target>
The example also takes me to my second argument. I do not think you should use your build folder as library folder, since this may lead to individual projects erroneously overwriting library assemblies e.g. by using Copy Local. You should have strict control over your library versions, so I suggest you keep this separated. (Developers would need to add this path in VS as a reference path.)
You may also choose to separate ..\..\Build into ..\..\Release and ..\..\Debug as suggested by ShuggyCoUk.
I like the top level Bin Lib folder setup that is common in Unix based systems, by the way moving to this type of system will also make your release engineer's life a lot easier as well. Installer Creation is much simplified by only having to pull everyhting out of one folder. Dll's would then go in bin..