views:

193

answers:

2

I have a couple of different solutions, in which some projects may depend on output from projects in other solutions. To manage this, I've been copying dll files from the /bin/ folder in each project to a shared library location after build, and then copy/reference them from there to the dependent project.

However, as the library solution gets larger, this tends to become unmaintainable. Too much of my time is being spent traversing solution directories in Windows Explorer looking for /bin/ folders, and trying to figure out which one, or which ones, of the dll files from each one I need.

Is there any way to give Visual Studio a hint that I want all projects in a solution to have the same output directory? For example, a /bin/ folder directly under the solution folder, where all projects put their output.

If possible, I'd like to achieve this without hard-coded post-build events that copy the files, since that will fail if a project output changes file name, or adds another file. I'd rather like to change the location of the actual output directory - the location of $(OutDir), if you will.

A: 

You can set the output directory in each project properties.

Right click on the project, select Properties

For C#, it is one of the Build property page, under Output, Output directory.

In VB.Net projects, it is on the Compile tab, in the textbox at the top.

Oded
My projects are mostly VB.NET projects, so the property pages don't look the same as for C# projects.
Tomas Lycken
Found it anyway =) However, this is on a project level. What will happen if two projects have dependencies on the same third project or third party dll - will they overwrite, rename or scream for help (i.e. throw exceptions)? What I'm after is - is there any way to do this on the solution level rather than on the project level?
Tomas Lycken
@Thomas - yes, on the project level. Exceptions will not be thrown and usually the dlls that are dependencies will be overwritten. This is not a problem as compilation of projects is sequential.
Oded
+1  A: 

I know you said you don't want to use post build events, but your reason as to why not intrigued me. It sounds like you might be hard coding the name of the .dll in your post build event. That can easily be avoided.

xcopy "$(TargetDir)*" "c:\common\" /Y

The * would just cause everything in your bin/Debug/ folder to get copied to your common folder. You could also just copy dlls if you want. Or, if you use $(TargetPath), you'll copy just the 1 dll that is the result of the project, and not any other related dependencies.

UPDATE

The way we do it is each projects entire bin folder is copied to a *sub*folder. Suppose you have 2 projects, WebUtil and HtmlParser, where WebUtil depends on HtmlParser. For both projects, use xcopy "$(TargetDir)*" "c:\common\$(ProjectName)" /Y. This will create c:\common\WebUtil\ and c:\common\HtmlParser. In WebUtil, add a reference to c:\common\HtmlParser\HtmlParser.dll. There will now be 2 copies of HtmlParser.dll in c:\common.

c:\common\HtmlParser\HtmlParser.dll // the most recent build. c:\common\WebUtil\HtmlParser // what was the most recent build when WebUtil was built

This has all kinds of advantages. If you change the API of HtmlParser, WebUtil will continue to work, since it will have the older HtmlParser.dll until you try to rebuild WebUtil (at which point you'll get build errors because of the changed API).

Now, if a 3rd project got in the mix that depended on WebUtil, and you're using some part of WebUtil that exposes classes in HtmlParser, then you'll need to add a reference to both projects from your new project. When you add a reference to HtmlParser.dll, use the one in c:\common\WebUtil. You do this because you're only including it as a necessary requirement of WebUtil. Now you'll always have the version of HtmlParser.dll that matches your current version of WebUtil.dll.

I hope that makes sense. It can definitely be a tricky thing to manage. Just wait till you have to start pulling down all your dependencies using svn:externals =P

Samuel Meacham
This still leaves me with one of two problems: Either (if I copy everything from bin) I risk copying too much and overwriting stuff from other projects, or (if I copy only the dll that is the result of the project) I risk ending up with too little in the builds folder, since dependencies that are needed could be left out. Is there no middle way?
Tomas Lycken
+1 this is exactly what i would have suggested. @Tomas, do you realise that you can filter the copy even more closely: `xcopy "$(TargetDir)*.dll" "c:\common\" /Y` to copy only the dlls. If that doesn't quite get everything then you could add another more specific copy command as well. This really isn't much of a hassle, its only a couple of minutes work and one or two test builds, and if you apply the right filtering to the `xcopy` then it is also low maintenance.
slugster