Stop Visual Studio 2017 From Autogenerating Output Directory - visual-studio

So I have a solution with 70ish projects that I updated to use a Directory.build.props file to use a single bin folder to make our CI process cleaner. Works great and now everything is in 1 locaction
BUT the problem now is when I open Visual Studio 2017 it creates a bunch of extra project folders now that NEVER get used. Anyway to disable this? It's just confusing to people and clutters up everyone's dev repo.
Example:
%sourceroot%\bin\release\ (this is where all the projects get happily binplaced)
%sourceroot%\bin\project1Neverused\ (unwanted folders that just clutter my dev box up)
%sourceroot%\bin\project2neverUsed\
%sourceroot%\bin\project1Neverused\
%sourceroot%\bin\project2neverUsed\
Here's my Directory.build.props file:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SolutionDir>$(MSBuildThisFileDirectory)</SolutionDir>
<OutputPath>$(SolutionDir)bin\$(Configuration)\$(MSBuildProjectName)</OutputPath>
<OutDir>$(OutputPath)</OutDir>
</PropertyGroup>
</Project>

Now open the sln file in Visual studio and if you look VS will have auto generated those folders even though you haven't built anything yet. I want that to be disabled because it's just generating junk folders that aren't used. Since we use a props file for msbuild to binplace we didn't update each project file from the default of "bin\debug"
Yes, Visual Studio will create those bin/obj folder by default when you create a new project/solution. It seems that there is no direct setting to prevent Visual Studio from generating these folders.
As a workaround, you can try to add a delete task in Directory.build.props file to delete the those folder:
<Target Name="CleanFolder" AfterTargets="Build">
<RemoveDir Directories="$(BaseIntermediateOutputPath)" />
<RemoveDir Directories="$(ProjectDir)bin" />
</Target>
Hope this helps.

Related

Create proj file that loads csproj files into solution explorer when opened with visual studio

I am building a project file for our application that I am going to execute from our build machine. I was wondering if it is possible for me to open the project file and get the same view visual studio gives me of the solution when I open a solution file.
So here is my Contosa.proj file so far.
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)'=='' ">Debug</Configuration>
<RootNamespace>Contosa</RootNamespace>
<AssemblyName>Contosa</AssemblyName>
</PropertyGroup>
<ItemGroup>
<Projects Include="C:\Users\localuser\Documents\Perforce\Contosa\Branches\Working23\UI\Desktop\ContosaClient\ContosaClient.csproj" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="Build">
<PropertyGroup>
<Contosa>$(MSBuildProjectDirectory)\UI\Desktop\ContosaClient\ContosaClient.csproj</Contosa>
</PropertyGroup>
<MSBuild Projects="$(Contosa)"
Properties="Configuration=QA;
VisualStudioVersion=12.0;
DevEnvDir=C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\;
SolutionDir=$(MSBuildProjectDirectory)\"/>
</Target>
</Project>
Currently double clicking this file with visual studio as its associated application will open the Contosa.proj for text editing. I would really like it to be possible to associate my Contosa.proj file with visual studio like our Contosa.sln file is. So when developers open it with visual studio they get the same view that you get from the Contosa.sln. I don't understand what parts of a csproj or a sln file make them open as projects or solutions in visual studio.
UPDATE 1
I am looking to do what this user Replace .sln with MSBuild and wrap contained projects into targets did but I want the project file to be able to opened by the user like a solution file. I want the Projects I include to be loaded into the solution explorer.
When visual studio installs, it configures explorer to launch visual studio when a .csproj is doubleclicked (How can I set a file association from a custom file type to a program). Your windows, and your developers windows, don't know what a .proj is. So rename it .csproj or distribute a .sln which references .proj

Is there a way to global set the platform toolset to v110 on VS 2013?

I've been perusing through similar questions on stack overflow and could not find a specific or definitive enough answer to this question:
I am currently using MSVS 2013 Ultimate, and have separately downloaded MS build tools 2013 as well. I am trying to install some npm modules that use the earlier platform toolset of MSBuild to compile and after following instructions from MSDN on how to Modify the Target Framework to a different platform, those did not help me successfully download the packages either. My current project is dealing with javascript and I'm not using visual studio in the near future, so I'm extremely flexible in terms of changing its configuration settings at the moment.
I am afraid that I'll have to resort to downloading VS 2012 in order to do this, unless someone found a clear cut alternative.
I am currently running everything on Windows 8 Enterprise x64.
Thanks in advance for all the help.
You can make use of the ImportBefore extension points for MsBuild: add propertysheets to
$(VCTargetsPath)\Platforms\$(Platform)\ImportBefore
and add properties to them forcing the PlatformToolset irregardless of what is set in the vcproj files. With VS2013 it is a bit more difficult to do this compared to VS2012 (I used this trick there to globally build everything using the v110_xp toolset) but it still works.
Suppose you are on a 64bit machine and want to override settings for all C++ projects for the Win32 platform, add a property sheet called override_platformtoolset.props (the name doesn't matter, as long as it ends with .props) to the directory C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\Win32\ImportBefore\Default with this content:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PlatformToolSet>v110</PlatformToolSet>
<DefaultPlatformToolset>v110</DefaultPlatformToolset>
</PropertyGroup>
<Target Name="ShowOverrideInfo1" BeforeTargets="Build">
<Message Text="Overriding PlatformToolset!" Importance="high"/>
</Target>
</Project>
Then add another file called override_platformtoolset to C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\Win32\ImportBefore with this content:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PlatformToolSet>v110</PlatformToolSet>
<ToolsetPropsFound>false</ToolsetPropsFound>
<MinSupportedVCTargetsVersion>v110</MinSupportedVCTargetsVersion>
</PropertyGroup>
<Target Name="ShowOverrideInfo2" BeforeTargets="Build">
<Message Text="Overriding PlatformToolset!" Importance="high"/>
</Target>
</Project>
The targets are just there to make sure you put the files in the correct location: if you build now, you should see the Overriding PlatformToolset! message twice (and see that cl.exe and link.exe are invoked from C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin). Else something is wrong.
If you wonder how/why this works inspect Microsoft.Cpp.Defaults.props and Microsoft.Cpp.props.props in C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120.

How do I use an MSBuild file from Visual Studio 2012?

I have a simple MSBuild file that I'm learning with.
Here it is:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Clean" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>{D5A16164-962E-4A6D-9382-240F31AB6C50}</ProjectGuid>
</PropertyGroup>
<Target Name="Clean">
<ItemGroup>
<BinFiles Include="bin\*.*" />
<fff Include="f\*.*" />
</ItemGroup>
<Delete Files="#(BinFiles)" />
<Delete Files="#(fff)" />
</Target>
</Project>
Now I want to include this in a Visual Studio solution and be able to run the "clean" target from Visual Studio 2012. I tried naming it testproject.msbuildproj like the internet seems to suggest "works", but it doesn't work. When I run the clean command I just get "unexpected error".
If I rename the project to testproject.csproj, it does some unintuitive things like creating compilation directories, but it does actually run my clean command properly. However, this is undesireable because it creates obj and bin/x86/debug type directories. It also looks goofy in Visual Studio because it still gives the References drop down.
How can I use just a plain vanilla MSBuild project from Visual Studio without random errors or false assumptions?
Note I only am having a problem with this from Visual Studio. Using msbuild from the command line it works perfectly
Visual Studio creates bin / obj folders when it opens csproj file. When you click Build / Rebuild / Clean it just uses appropriate targets from the project file.
You cannot stop VS from creating these folders, but you can ask it to create them in say temp folder by setting appropriate properties - refer this MSDN article for details.
So the steps are to rename your project to csproj, and add the following lines into project:
<PropertyGroup>
<OutputPath>$(Temp)\bin</OutputPath>
<IntermediateOutputPath>$(Temp)\obj</IntermediateOutputPath>
</PropertyGroup>
I usually use a bit different approach to work with MSBUILD files from VS:
I use regular csproj file with removed Import ... CSharp.targets part as pure container for my Build projects.
I add actual build files with targets and logic, and all properties, necessary artifacts like XSLT etc using "Include into project", so I can manage hierarchy and change any file from within VS.Net.
I redefine Build / Rebuild targets in csproj file for whatever I need, for example Build may contain minimum output, and while rebuild diagnostic one.
Like this:
<Target Name="Build">
<Exec Command="%windir%\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe Builds\build.proj /t:Build /v:m" />
</Target>
<Target Name="Rebuild">
<Exec Command="%windir%\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe Builds\build.proj /t:Build /v:d" />
</Target>

Build doesn't work from VisualStudio, but is ok from msbuild

From a brand new console application template in visual studio, I edited the .csproj to build another project like this:
...
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="BeforeBuild">
<MSBuild Projects=".\other.mproj"/>
</Target>
...
Where other.mproj is:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<Target Name="Build">
<Message Text="kikou" />
</Target>
</Project>
After a while I discovered that modifying the content of other.mproj (for instance, by introducing errors or changing text kikou to something else) would not be taken into account unless unloading/reloading the project in visual studio.
Building from the command line with 'msbuild myproj.csproj' immediatly detect changes in 'other.mproj'. So it all looks like visual studio is working from a cached version of other.mproj file.
Why is visual studio caching this other script (which is even not included to the project), and how can I solve this issue ?
Update: I also tried this UseHostCompilerIfAvailable, it doesn't work.
NB1: I didn't add other.mproj as a project reference in the .csproj because it is not a .NET project at all (it just creates resources files for the .csproj from other inputs before the build)
NB2: I'm using VS2010 (10.0.10219.1SP1Rel + MSBuild 4.0.30319.1)
Visual Studio caches all MSBuild files, this is done for performance reasons. You will not be able to have an MSBuild only way around this. It may be possible to achieve this via a VS add-in but I'm not 100% sure of that.

MSBuild targets file doesn't cause outputs to be built, even though inputs are newer

I am trying to create a msbuild/VS2010 .targets file for flex, so that I can use .l files in Visual Studio 2010. So far, I have produced this:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<LFiles Include="$(MSBuildProjectDirectory)\**\*.l"/>
</ItemGroup>
<Target Name="Flex"
BeforeTargets="ClCompile"
Inputs="#(LFiles)"
Outputs="#(LFiles->'%(RootDir)%(Directory)%(Filename).c')"
Returns="#(LFiles->'%(RootDir)%(Directory)%(Filename).c')">
<Exec Command="flex.exe "-o%(LFiles.RootDir)%(LFiles.Directory)%(LFiles.Filename).c" "%(LFiles.FullPath)" 2>&1 | sed -e "s/. line \([0-9]\+\)/(\1)/" | sed -e s/\"//g"/>
</Target>
</Project>
I added this file to my project, using the Build Customizations... dialog. I then added my .l file, scan.l, and built the project - scan.l was created in the expected place, suggesting that the file name transformations are working. Next, I added scan.c to the project, and built the project again. The generated .c file compiled correctly, and the project linked. So it seems that things are basically working.
My expectation was that Visual Studio would then invoke flex if the .l file changes. The target's Inputs attribute includes the .l file, and its Outputs attribute includes the .c file, and Visual Studio can check whether the input is newer than the output. But in fact, this doesn't happen. If I just change the .l file and rebuild, Visual Studio tells me everything is up to date.
If I delete the .c file and build the project, the .c file is regenerated, just as I'd expect. But if I just change the .l file and build the project, nothing happens. In fact, in this case, msbuild doesn't even seem to run! If I delete the build log before building, Visual Studio tells me that everything is up to date, and no new build log is produced. This makes it rather hard for me to work out what might be going on.
This is my first go with msbuild, so I am probably doing something wrong. But what?
(N.B. my targets file might fall over with multiple .l files, or suffer from some other flaw(s) unrelated to the dependency checking issue - I am not bothered about any of this at this stage.)
To figure out the fix, I realised I could create a Visual Studio 2008 project with a .rules file, load it into Visual Studio 2010, let Visual Studio 2010 convert it automatically, and examine the result. So I did that.
To fix the problem, add an XML file with the same base name as the targets file. This one will do for this example:
<?xml version="1.0" encoding="utf-8"?>
<ProjectSchemaDefinitions xmlns="clr-namespace:Microsoft.Build.Framework.XamlTypes;assembly=Microsoft.Build.Framework" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:transformCallback="Microsoft.Cpp.Dev10.ConvertPropertyCallback">
<ItemType
Name="Flex"
DisplayName="Flex" />
<FileExtension
Name="*.l"
ContentType="Flex" />
<ContentType
Name="Flex"
DisplayName="Flex"
ItemType="Flex" />
</ProjectSchemaDefinitions>
Next, refer to this file in the ItemGroup section. The .targets file is pretty small so here's the new version in its entirety:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PropertyPageSchema Include="$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml"></PropertyPageSchema>
<LFiles Include="$(MSBuildProjectDirectory)\**\*.l"/>
</ItemGroup>
<Target Name="Flex"
BeforeTargets="ClCompile"
Inputs="#(LFiles)"
Outputs="#(LFiles->'%(RootDir)%(Directory)%(Filename).c')"
Returns="#(LFiles->'%(RootDir)%(Directory)%(Filename).c')">
<Exec Command="flex.exe "-o%(LFiles.RootDir)%(LFiles.Directory)%(LFiles.Filename).c" "%(LFiles.FullPath)" 2>&1 | sed -e "s/. line \([0-9]\+\)/(\1)/" | sed -e s/\"//g"/>
</Target>
</Project>
Now reload the project, and visit the properties for the .l file. Select the new Flex option from the Item Type dropdown. This seems to prod Visual Studio into taking a little more care over the file.

Resources