MSBuild not copying a DLL, while Visual Studio does - visual-studio-2010

In our Visual Studio 2010 project we reference - among the others - the SmartAssembly.Attributes.dll and it's properly copied to the Bin/Debug or Bin/Release folder of our local dev machines. On the build server this is true for all other references but not for 'SmartAssembly.Attributes.dll'. The build succeeds.
What should I check?
Thanks.

Open your .csproj file (or .vbproj file), and look for the assembly reference. Then make sure the hint path is still valid in your build server. Sometimes VS2010 will add an absolute hint path, instead of using one relative to the .csproj file itself, so the drive letter may be invalid in another machine.
For example, the reference may look similar to the one below (I made up all of the XML below to illustrate only and it's NOT valid), and the absolute hint path may be invalid in the build server (e.g. there's no drive letter d there):
<Reference
Include="SmartAssembly.Attributes, Version=8.0.0.0,
Culture=neutral, PublicKeyToken=b03f1f7f1ad5da3a,
processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<Private>true<Private>
<!-- The HintPath below should exist and be valid in your build server -->
<HintPath>d:\temp\SmartAssembly.Attributes.dll<HintPath>
</Reference>
You can change the HintPath to make it relative to the .csproj file and therefore more general. For example:
<HintPath>..\libs\SmartAssembly.Attributes.dll<HintPath>
Another problem may be that <Private>true<Private> isn't there. This attribute mapped to the CopyLocal property in Visual Studio, so if it's missing from your .csproj, the DLL won't get copied to bin\Debug or bin\Release by MSBuild. See http://bronumski.blogspot.com/2009/06/project-reference-fun-and-games.html

Related

Visual Studio Addin - Changing project references after project load without "really" changing them

So our build system and source control system is from Perforce, which is a piece of poopers.
We want to change reference to dlls in the project to some other location, for example, current reference might be C:\blah\debug\blah.dll, we want to change it d:\codeinjected\blah\debug\blah.dll
But we don't want to do this is the VStudio project file, because that is also our MSBuild build lab file, so is there a way to make an addin that can do it on the fly, without actually changing the references?
It sounds like you situationally want to change the location of reference DLL's for a Visual Studio project. The easiest way to do this is to add condional constructs into the MsBuild file itself.
<Reference Condition="$(OnDevMachine)">
...
</Reference>
<Reference Condition="$(OnLabMachine)">
...
</Reference>
Another option is to have a common msbuild file for all of your projects. In that particular project you can create a conditionally defined value pointing to the reference directory and have every leaf project reference that variable. It will be less code and possibly more amenable to your build guy.
<PropertyGroup>
<ReferenceDir Condition="$(OnDevMachine) == 'true'">Some\Dev\Path</ReferenceDir>
<ReferenceDir Condition="$(OnLabMachine) == 'true'">Some\Lab\Path</ReferenceDir>
</PropertyGroup>

Why visual studio delete non-related assemblies from Bin folder when rebuild

I have an asp.net mvc web application, and i have a reference to SharpArch.Web (one of the Sharp Architecture assemblies)
When i rebuild the project, and run it, an exception is thrown telling me that the (Newtonsoft.Json.dll) is missing from the Bin folder which is used by (SharpArch.Web), so it's ok, i copied it, and every thing worked well.
When i try to rebuild the project again, the exception is thrown again, and the (Newtonsoft.Json.dll) assembly is deleted ??
Why did that happen? what does visual studio have to do with non-referenced assembly ?
and FYI, VS doesn't delete everything from Bin, just a specific assemblies !!!
and BTW i don't want to add a reference to (Newtonsoft.Json.dll), i don't like to reference an unused assembly.
I had the same situation on one solution I was working on. So I ended up putting those .dll's into a separate folder. In my case I named this folder "ServerAssemblies". Then I modifyed my project file (.csproj in my case) and added an "AfterRebuild" target. That way there is noe need to add references to unused assemblies to the project.
<Target Name="AfterRebuild">
<ItemGroup>
<ExtraAssemblies Include="$(SolutionDir)ServerAssemblies\**\*.*"/>
</ItemGroup>
<Copy SourceFiles="#(ExtraAssemblies)" DestinationFolder="$(ProjectDir)bin\"></Copy>
</Target>
I suppose that the Bin\ directory is reserved for mangling by Visual Studio. You'll have to put your assembly in a different location.

Reference DLL file not copying to bin with deployment project, causing error

We have several external DLL files being referenced in our Web Application Project. We have a deployment project for installing on the hosting servers. When we were using .NET 3.5 and Visual Studio 2008 the DLL files were being copied to the bin folder. Since we have upgraded to .NET 4 and Visual Studio 2010 this no longer happens, and we are getting server errors since the references cannot be found.
CopyLocal is set to true, and I cannot find anything inside the web.config which suggests this is being set elsewhere.
There is a bug in Visual Studio 2010. By default the XML in the solution file looks like this:
<Reference Include="DevExpress.SpellChecker.v11.1.Core,
Version=11.1.5.0,
Culture=neutral,
PublicKeyToken=b88d1754d700e49a,
processorArchitecture=MSIL">
<HintPath>..\References\DevExpress.SpellChecker.v11.1.Core.dll</HintPath>
</Reference>
Whereas MSBuild is expecting this below, so that the DLL file will be included in the deployment:
<Reference Include="DevExpress.SpellChecker.v11.1.Core,
Version=11.1.5.0,
Culture=neutral,
PublicKeyToken=b88d1754d700e49a,
processorArchitecture=MSIL">
<HintPath>..\References\DevExpress.SpellChecker.v11.1.Core.dll</HintPath>
<Private>True</Private>
</Reference>
The trick is to set Copy Local to False, save the project and then reset it to True - save again. This includes the Private node correctly, which MSBuild respects.
It appears that the default for no included private node (Copy Local) in Visual Studio 2010 is True, while MSBuild reads that missing node as False.
I was getting the same problem and rather than add a "BeforeBuild" step I created a test that simply did this
[TestMethod]
public void ReferenceAssemblyThatDoesNotCopyToBuildFolder()
{
Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler referenceThisButDoNotUseIt = null;
}
And that fixed the error The type 'Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler...' cannot be resolved
Something weird had happened to my deployment project. When I saw it had no detected dependencies, I removed the primary output and re-added it.
The dependencies are now showing up and being placed in the bin folder when installed.
I was getting exactly the same issue. We have a Visual Studio 2008 project which references the EnterpriseLibrary. When we run our integrated build using TFS and our Web deployment project, all the DLL files are copied over. When we upgraded to Visual Studio 2010, TFS 2010 and WDP 2010, some of the DLL file's were missing. Strangely, this only occurs to some DLL files and not others.
For example, we get the Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.dll copied in both cases, but not the Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.dll.
As a workaround I copied the files accross using a "BeforeBuild" step.
It now seems to build OK.
I just had the same issue and wanted to share what I found as it might help someone:
The reason in my case was that the assembly was installed in the GAC during an installation of some third-party application.
If the DLL file is in the GAC, the compiler won't bother to copy it to the destination folder, unless you specifically mark it for "copy local" using the "Private" node in the project file as mentioned by Junto.
The thing is that if you don't add that node, and you develop on one machine and build on a different one, and the DLL file is only in the GAC of the build machine, the default behavior without the private node will cause the file to be copied correctly on the development machine, but not on the build machine.
The bigger problem is if the DLL file is not referenced directly, but the project references a second project that in turn references the DLL file. In that case, you cannot mark the DLL file to be "copy local" in the project, as it is not referenced by it. So if the DLL file exists in the GAC - it won't get copied to your output folder.
Possible solutions to this case are:
Uninstall the DLL file from the GAC
Add a direct reference to the DLL file in the end project(s)
Re-sign the DLL file with a new strong name, which will differentiate it from the DLL file in the GAC.
I am not sure how it was set up in Visual Studio 2008, but I am almost positive that you might have been using the Post-Build event command line. In there you can tell to copy the DLL files you need for deployment. An example is given below:
mkdir $(SolutionDir)\Deployment
copy "$(SolutionDir)Your_Library_Name\Your_Dll_ForDeployement.dll"
$(SolutionDir)\Deployment\
I didn't meet the same problem but similar. I had WPF main project and referenced project where the referenced did not copy. I found that in my case the main project was set for NET 4.0 Client Profile and the referenced for NET 3.5. When I set the main project to 3.5 the compiled dll of the referenced project started to copy.
(I don't know why because I solved it by practice)
I too ran into a similar issue where referenced dlls were not copied into the bin in published folder. I was using a TFS checked out copy that didn't include the bin folder into the application.
-> So just included the bin folder.
-> Built the referenced applications
-> Published the website project
Now I see all the referenced dlls in bin in the published folder
I had a similar issue with VS 2012 Express. I used Tesseract libraries in my project. Everything worked well until I used this project in a solution where were more than one project. Problem was that some DLLs (liblept168.dll, libtesseract302.dll) that are normally placed in folders bin/debug/x86 or bin/debug/x64 were copied only when I rebuilt whole solution.
Changing a single line and building it again caused that the DLLs were deleted and not copied back.
I solved this issue by adding a reference of the project that creates missing DLLs to the startup project.
rzen and others, thanks - your comments led to a solution for us.
We have a project that targets version 10 of the Microsoft.ReportViewer.Common.dll and Microsoft.ReportViewer.WebForms.dll assemblies (separate "libs" folder we created at the 'src' level). But when we did a build, the output included version 12, which was recently installed on the build server.
Using comments here, we ensured that 'Copy Local' was set to True and that the flag was set in the project file. However, it was still deploying version 12. So what we found that did the trick was ensuring that the 'Specific Version' property was also set on the two references. Voila, version 10 of each file is now being deployed!
There was much rejoicing.
JH
If your project does not directly load the library, it won't always be deployed, even if it is referenced explicitly! I got confused because I could see it in a local Bin directory but not when deployed. The dll in the Bin directory was an old file that wasn't removed during Clean which is why I was confused.
A full clean and rebuild and it wasn't in my local Bin folder either which showed me the problem (I only use it in web.config). I then referenced the dll file itself in the project and set it to copy to output to make sure it gets deployed.
We can use the <Private>False</Private> to not to copy the referenced DLL files to the bin directory. This is useful when we are building applications in a separate TFS build server where we need to build the application and not to copy the DLL files to the bin directory.
Check the framework of the project in which the DLL file has been referenced. The framework should be .NET 4.0. Please correct it if the framework is Client Profile.
Adding the parameter
/deployonbuild=false
to the msbuild command line fixed the issue.
Got a similar issue when upgrading old WebSites into WebApplications.
The "Clean Solution" command would wipe out all external DLL files I purposely left in my bin folders.
Besides, it was not possible to bring those DLL back automatically simply by referencing them all, since many of them have the same file name (it happens when you work with many language specific resources)
Like stevie_c did, I took advantage of the Pre-Build command, but made it simpler:
I just used a xcopy command in the Pre-Build operation of the WebApplication project's properties. This way I could bring over the necessary external DLL files just before the build would start.

How to get Visual Studio to stop copying DLLs during build without my permission?

I have a Visual Studio project that relies on several DLL references. Here is a sample of those references in my csproj:
<ItemGroup>
<Reference Include="Class1.Project1">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\bin\Class1.Project1.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Class1.Project2">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\bin\Class1.Project2.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
However, when I include this class as a project dependency in a web site project, Visual Studio is finding dependencies of the dependencies shown above. During build Visual Studio is then defaulting the "Copy Local" property to "True" and copying these dependencies into my web site's ~/bin directory.
This, in turn, is overwriting the versions of the DLL files that already exist in this directory. This causes the following error:
Could not load file or assembly
'Class5.Project5, Version=3.6.1861.2,
Culture=neutral,
PublicKeyToken=dfeaee0e3978ac79' or
one of its dependencies. The located
assembly's manifest definition does
not match the assembly reference.
(Exception from HRESULT: 0x80131040)
How do I make Visual Studio default the "Copy Local" setting to "False" for everything? I do not want Visual Studio to copy DLL files automatically during build. Nor do I want to tie my build to very specific versions of a DLL.
It sounds to me as though you have multiple projects configured to output into the same directory - is this true?
If so, you'll need to review your configuration as Visual Studio assumes (nay, requires) that each project has a unique output directory.
Also, you wrote:
This, in turn, is overwriting the versions of the DLL files that already exist in this directory.
Where did these existing files come from?
Visual Studio assumes that it has full rights to make whatever changes it sees fit in the build output directories - trying to argue with it is a fine route to a whole new world of pain.
(Unfortunately, I speak from experience. Sigh.)
I had this problem once,
On Publish: The easiest way to prevent writing over the existing dll files is to set them as ReadOnly. You will get a warning on publish for each file that could not be replaced but it will do the job.
On Build: To set the CopyLocal automatically off you need to place the dll files on the GAC.
Why were there other versions already in the bin directory?
In any case, I wonder if you would get the same problem using a Web Application Project. Since it's a project, it has a single file listing the direct references, and if these are project references (references to the output of other assemblies in the same solution), then MSBUILD can ensure that the correct version is used.
See if you can reproduce this by starting with a new web application project and just adding the references.
You could try the following in your project file.
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
And then, in your code try this.
<ItemGroup>
<Reference Include="Class1.Project1">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\bin\Class1.Project1.dll</HintPath>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</Reference>
<Reference Include="Class1.Project2">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\bin\Class1.Project2.dll</HintPath>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</Reference>
</ItemGroup>

Visual Studio: How to reference assemblies in Visual Studio?

i have a debug and a release version of an assembly dll.
They are sitting is directories on my computer. For other developers they are sitting in directories on their computer.
For the debug version of the application i want to use the debug assembly. For the release version of the application i want to use the release assembly.
That's the question.
For those not paying attention, there are quite a few issues here. How to reference an assembly on my computer, which after the project is checked into source control becomes a valid path on someone elses computer.
How to have the "References" node be per solution type (Debug, Release).
i tried copying the debug assembly to
\bin\Debug
and the release assembly to
\bin\Release
and added the assembly dll's to source control in the
\bin\Debug
\bin\Release
folders. Then i hope that the assembly would be found in the executable's folder.
Problem with that is that other developer's machines get an error that the assembly dlls could not be overwritten - when CopyLocal is false.
Use a common structure for these DLLs (a common directory-name) and link to this relative.
Example from a .csproj-file:
<Reference Include="utils_xxx, Version=1.2.10.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\common_utils_dllproject_dir\utils\bin\$(Configuration)\utils_xxx.dll</HintPath>
</Reference>
You maybe have to enter this by hand, but once in the repo, it is the same for all. Now you just have to convince your developers to adjust to this directory-layout and -naming.
PS: If you overlooked it: $(Configuration) is the trick to use Release/Debug-DLLs.
Developers must have a folder somewhere on their machine structured like this...
[Parent Folder]
Debug
[Debug Assembly].dll
Release
[Release Assembly].dll
Open the project and add a reference to the Debug assembly from the first step. Check it in.
Have every developer open the project and add a reference path in the project properties. The path should be an absolute path to the Debug folder from the first step.
Have every developer close Visual Studio and edit the [project].user file that is now in the same folder as the project file. Change "Debug" to "$(Configuration)". Save and close.
This should now work. If you select the reference in the Solution Explorer and look at the Path property in the Property Grid, it may not be correct. It's just a VS issue. If you test building in Release and Debug, it should work.
This works because the reference paths that developers set are stored in a user file that never gets checked into source control. Therefore, the paths can be different for every dev. This solution is basically stolen from Leonidas' answer but uses reference paths.
Disclaimer
I don't know all the details of your situation, but I personally wouldn't do this. I would probably GAC the release version of the assembly on the developers' machines. Then I would have a build script that ran on a server that would take care of your complicated scenarios.
Include the project and link to the project? dont know if that does work in your situration...

Resources