How to avoid Visual Studio outputs assemblies in Target Framework Name directories? - visual-studio

We have some netstandard2.0 assemblies. When compiling they are generated within the directory .\bin\Debug\netstandard2.0 (netstandard2.0 dir name is the TFN the Target Framework Name). However only .\bin\Debug is specified in Project Properties. And we'd like to generate those assemblies within .\bin\Debug to get all our assemblies with the same directory.
We developed a Post-Build event to copy back our assemblies and their json/pdb files within .\bin\Debug and then delete the dir .\bin\Debug\netstandard2.0. However this is not a good solution because the FastUpToDate tool used during incremental compilation does'nt find .\bin\Debug\netstandard2.0\ProjectName.pdb and thus our netstandard2.0 projects are always rebuilt even when they are up-to-date.

Set AppendTargetFrameworkToOutputPath to false in your projects.
<PropertyGroup>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>

Related

Visual Studio 2022 ignores BaseIntermediateOutputPath property specified in project files

I have a solution containing a large number of projects.
To separate binaries from the sources, I changed BaseOutputPath to "..\bin" and BaseIntermediateOutputPath property in all projects to "..\obj".
It worked for the BaseOutputPath - all binaries are in the common directory.
For the intermediate path it didn't work at all. It broke the projects, because the obj directory is still created in the project folders, but now the files are not excluded from the project and appear as commitable for Git.
What am I doing wrong? Is it normal behavior? I don't want obj directories created in project directories. How can I achieve that behavior?
For now I just removed the property from projects. At least the obj folders are not shown as project folders.
You need to use MSBuild macros such as $(SolutionDir) or $(MSBuildThisFileDirectory) and similar, if you do not want relative paths to start from your project file.
For example, you could set "BaseIntermediateOutputPath" to $(SolutionDir)\obj or better still to $(SolutionDir)\obj-$(Configuration). This way you will separate Debug and Release builds, which, if you don't, will get you into a lot of trouble.
Here is what I use in a particular "Directory.Build.props". Note the <OutDir> entry. This will change the output directory for all projects under this directory to the stage64\lib directory.
<PropertyGroup>
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<OutDir>$(SolutionDir)..\stage64\lib\</OutDir>
</PropertyGroup>

Why does Visual Studio 2019 deletes my referenced assemblies after the build?

I have a Visual Studio 2019 solution that I inherited from someone else with multiple projects.
I'm trying to build one of the projects in particular.
I have a reference to an external assembly with "copy local" set to true.
When I build my project, my referenced assembly gets copied over tot he output folder but then it gets deleted.
I know it gets copied because I have tried using the post build event "dir $(TargetDir)" and it shows the dll.
Any idea why it would get deleted afterward?
The problem was caused by by these lines in my csproj file:
<Target AfterTargets="AfterBuild;NonWinFodyTarget" Name="CleanReferenceCopyLocalPaths">
<Delete Files="#(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
</Target>
The solution was using Fody to weave the assemblies.
I had removed the weaving, but this line in the csproj file was a left over from the use of Fody.
The issue is that you have used some nuget packages like Costura.Fody which could merge your specific external assembly into the main output file while it is set to Copy Local True.
So please check if your FodyWeavers.xml file has any merge operation of your external assembly.
In my side, I have an external assembly called ClassLibrary22.dll and set it to CopyLocal to true.
And add these on FodyWeavers.xml file:
So the assembly ClassLibrary22.dll will be merged into the main project exe or dll output file and did not exist under output folder.
That is the cause.

Different results with MsBuild and Visual Studio

I have a solution, which consists out of 2 projects: regular class library for .NET 4.5 + website (not web application) project.
When I build this solution with Visual Studio - all referenced assemblies from Nuget packages and local references are copied to bin folder of website project.
If I try to build solution with MsBuild - bin folder of website project does not receive any assemblies.
Website project is not selected to be built in VS configuration (which is reported by message in both cases)
Edit - here is additional explanation.
When I clone a project from git - bin folder of website contains only 4 assemblies already checked in:
If I will run msbuild command with /t:Build or /t:Rebuild and /p:Configuration=Release;Platform="Any CPU" - I'll receive just an output of postbuild event in my other project, included in solution:
However, if I execute build from VS (Ctrl + Shift + b) in Release/Debug config - bin have all required assemblies for running web application.
Edit 2: Link to example solution - https://github.com/akuryan/csharp-website-test
When one builds it with msbuild TestApp.sln /t:Rebuild /p:Configuration=Release;Platform="Any CPU" - this results in only Test.Core.* and LetsEncrypt.Umbraco.dll (initially checked in) found at ~\Test.Web\bin\ (where Test.Web is website project). If one builds TestApp.sln with VisualStudion 2015 (I suppose, 2013 and 2017 will be the same) - ~\Test.Web\bin\ gets whole amount of assemblies.
Different results with MsBuild and Visual Studio
That because the all dll.refresh file in bin folder alongside the binary file are ignored by .gitignore.
Since Web Site projects do not have any project file (.csproj) to put the assembly references, the *.dll.refresh files are used by MSBuild to understand the assembly references. The contents of the file is the relative path to the .dll via the packages folder for the solution. When you ignore all those .dll.refresh by .gitignore, MSBuild could not understand how to handle the dll files.
To test this, I created a website project, add a nuget package to it, then delete the dll files but keep the .dll.refresh files in the bin folder. Build the website project by MSBuild command line:
msbuild.exe TestWebsite.sln /t:Rebuild
After this command complete, the dll files are copy to the bin folder.
So build and package restore to work it looks like you need to keep the .dll.refresh files in the bin folder. You can remove the other binaries from your version control system.
Note: If you want to get those .dll.refresh back, you can use the command line in the Package Manager Console:
update-package -reinstall
Hope this helps.

devenv copies files from other project during incremental build

I have 3 projects; Project1.Web, Project1.Service and Project1.Common.
Both Project1.Web and Project1.Service have dependencies on Project1.Common.
If I rebuild the solution which contains all 3 projects; all works correctly.
If I change a file in Project1.Web; files are built to Project1.Web\bin - all works correctly.
If if change a file in Project1.Service files are built to Project1.Service\bin\Debug AND some are copied to Project1.Web\bin. The copied file is Project1.Common.dll, but Project1.Web.dll is not built (or copied).
The file modified in Project1.Service is not shared, its just modified to trigger an incremental build of Project1.Service.
Does anyone know why Visual Studio would be copying a build artifact to a a directory that is not part of the incremental build?
Currently this sequence of events leaves Project1.Web is a non-working state as Project1.Service and Project1.Web have dependencies on different versions of the same assembly via a third party assembly. If we decide to make a change to Project1.Service then it has the side-effect of breaking Project1.Web.
I've tried/checked the following:
There are no dependencies between Project1.Web and Project1.Service (either direction).
The file modified in Project1.Service is not shared; and there are no pre/post build events defined.
Executing msbuild on the Project1.Service.csproj project file does not have the same effect.
Denying write/create permission on the bin directory under Project1.Web does not cause the incremental build to fail.
No output is emitted in the detailed or diagnostic msbuild output that references Project1.Web (from within Visual Studio)
Using procmon, I can see that devenv is using mswebprj.dll (C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Packages\mswebprj.dll) - which invokes the copy of the file.

Anyone else notice that $(SolutionDir) resolves to ProjectDir when loading Wix projects into Vs2010?

I'm using Vs2010 and Wix 3.6.0917.0, for the record. I use the $(SolutionDir) property quite a bit in my .wixproj file, since I only ever build the installer as part of a solution build or as part of a team build, and never by itself. However, while building from the command line works just fine (both from cmd on the desktop and when building on build agents), when I attempt to reload the .wixproj file into the IDE, I get errors because all the $(SolutionDir) variables are resolving to the project directory, not the solution directory. Consider:
C:\workspace\projectCollection\teamProject\branch\solution.sln
C:\workspace\projectCollection\teamProject\branch\source\installer\installer.wixproj
and assume a shared custom targets file:
C:\workspace\projectCollection\teamProject\branch\build\shared.targets
which is referenced inside installer.wixproj with:
<Import Project="$(SolutionDir)build\shared.targets">
Command line builds work fine...
C:\workspace\projectCollection\teamProject\branch\> MSBuild /t:build /property:Platform=x64;Configuration=Debug solution.sln
0 Errors
0 Warnings
Build succeeded!
But load into vs2010 and you see...
The imported project
"C:\workspace\projectCollection\teamProject\branch\source\installer\build\shared.targets" was not found.
Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.
C:\workspace\projectCollection\teamProject\branch\source\installer\installer.wixproj
You can see here that the resolved result of $(SolutionDir)build\shared.targets is getting the project directory and not the solution directory. What gives?
My guess would be that $(SolutionDir) resolves to nothing when the wixproj is being loaded into VS2010. In this case the imported file becomes "build\shared.targets". Since the path is relative it is assumed to be relative to the project directory. Using ".." or some other path could get you around the problem.
I verified this failed with WiX 3.5.2222.0 in VS2010. A C# console application project (csproj) worked as expected.
Have you filed a bug against WiX for this?
I looked at the WiX vs2010 addin code a little bit and the Solution properties are only created when doing a build and not when the project is loaded.

Resources