Copy External Configurations to Local Projects in Visual Studio? - c#

What is the easiest way to create a build configuration in approximately 50-100 projects (same solution) IF Visual Studio has already detected the build configuration from another project?
Our team uses a set of common projects (namespace is simply "Common") within several solutions. The Common namespace has it's own master solution with its own set of build configurations. Common's solution contains five build configurations ("Debug-QA", "Debug-Dev", etc.).
Whenever these projects are used within a NEW solution (ie "MyNewSolution"), Visual Studio shows the build configurations from Common's master solution. Unfortunately, these configurations have not yet been created in MyNewSolution or any of MyNewSolution's projects. This creates a problem for ADDING the build configurations to the other projects, or including the projects in these build configurations, since there is no way to CREATE a build configuration if the name already exists (which Visual Studio thinks it does, thanks to the Common projects being included).
My goal is to add the same configurations (ie "Debug-QA", "Debug-Dev", etc.) into MyNewSolution, and its projects, so that all of the projects and solutions match. The only way I can see to do this is to manually create the build configuration on each new project... which is torture since MyNewSolution has approximately 50-100 projects.
FYI: I'm using Visual Studio 2012

This is more of a hack than a proper solution, but you could always:
Create a a copy of the configuration you want for the entire solution with a GUID as its name.
Remove the copy from the projects which already have the original configuration (undo changes).
Rename the GUID to the original configuration's name using the "Find/Replace in Files" tool.
Even if it isn't a very viable option, it is a pretty good quick fix.
EDIT:
How to manually remove configurations from solutions:
With the solution file opened in a text editor, you will see a block called Global which contains sections. The SolutionConfigurationPlatforms section contains the configuration's definitions. There is also an other section called ProjectConfigurationPlatforms where the configurations are assigned. Simply remove the references to the configuration from both groups and that should do it. If you have more complex solutions, there might be other references to remove. This is just a base case.
How to manually remove configurations from projects:
Again, with the project file opened in a text editor, you will see many references to the configuration you want to remove. C# projects have a PropertyGroup with the configuration as a condition. You can simply remove the group entirely. There might be other references to the configuration around the file so make sure to clean everything properly.
Make sure that you have a backup of your files if something goes wrong.

If there is very little project-level customization of the target configurations, this would probably be simplest to manage via an externalized configuration imported into your individual projects via the MSBuild Import element.
In order to allow project-specific overrides, this Import should be placed near the top of the project files. e.g.:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\CommonConfig.targets" Condition="Exists('..\..\CommonConfig.targets')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
...
This would, unfortunately, require you to edit all the project files once to add the Import. However, once this is done, you would be able to add a configuration to the imported .targets file and have it automatically propagate to all the projects.

I can't tell you what will work best for you, but I can say from experience that it becomes very easy to create new solution spaces with 50+ projects from old solution spaces when you don't let Visual Studio write the project files. Instead, you can take off-the-shelf third-party software that will read some configuration files you give it and in a few seconds will spit out a solution and all the projects you need, all configured the way you need them to be.
The same software would also generate the standalone "Common" solution when you just want to compile the common projects.
The right software will give you the flexibility and power that makefiles provide when you're setting up your projects, but you still get to do your work in Visual Studio.
I've used CMake extensively in that role, but for C++ rather than C#. I'm very happy with CMake; I have used it in environments with 50+ projects whose source code is scattered so far and wide that I use scripts to find it all, with some third-party libraries that are brought in as precompiled DLLs or LIBs. Also, from experience I know there's nothing stopping someone from concurrently maintaining their own hand-crafted set of VS project files for the same source code if they really want to. But of course you may want to do your own shopping around for the best software for your environment.
It is a significant investment of time to convert several dozen projects from hand-crafted project files to a more makefile-like system, but in an environment that requires reconfiguring or recombining the projects many times, I felt the investment paid back rather quickly.

Related

Visual Studio Addon that can warn developers when it detects that certain kind of references have just been added to a project?

We've all done it. We create a new class and type away the constructor adding dependencies and what not. Resharper is there to offer a helping hand and add missing references for us. It's only later on that we realise that we auto-imported references to other parts of our project that we shouldn't have.
So is there an addon for VS that one can configure (using wildcards etc) to have it issue warnings when/if certain .csproj projects are found to contain references to other .csproj projects that they aren't "allowed" to access (architecturally speaking).
Addendum: I am aware that I can achieve this by using pre-build msbuild-logic which parses the .csproj file using regexes and of course this would work. But I just find it kind of ... cumbersome and non-intuitive.
So is there an addon for VS that one can configure (using wildcards
etc) to have it issue warnings when/if certain .csproj projects are
found to contain references to other .csproj projects
AFAIK there's no such kind of extension that does the checking and warning job for you.
The reference to .csproj is actually project references in visual studio.
You can right-click project=>Build Dependencies=>Project Dependencies to check if current project depends on other projects in same solution.But this option will check both project references(add reference to xx.csproj in current.csproj) and project dependencies(ProjectDependencies section in .sln). So only use project references in your solution to manage dependencies between projects, then this option can easily check project references for you.
If the pre-build msbuild-logic which works need similar changes in every project in the solution, maybe Directory.Build.props can make some help if the changes in the project file have similar format. Fetch the pre-build logic into it and put this file in solution or repos directory, it reduces duplicate content in every project file.

Is it possible to force MSBuild to Only Build A Project Once, Regardless of Properties?

I am currently migrating a large solution from the old csproj file format to the new csproj format. I am doing this a few projects at a time, so I have a mixed environment with some projects using the old project file format and some projects using the new project file format.
I have started to notice some builds failing because files are in use. My theory (based on this answer) is that MSBuild is building some projects twice because the properties are different (i.e. the new project file format specify the TargetFramework property while old projects do not).
The projects that seem to have concurrency issues are projects that are referenced by other projects, where the referencing projects are split between the project file formats.
The command I am using to build the project is:
msbuild.exe /maxcpucount:6 /property:Configuration=Debug;Platform=x64 /t:Rebuild my.sln
Is there a way to instruct MSBuild to only build a given project once (regardless of properties) until I am able to convert all of the projects in the solution over to the new project file format?
Note that building single threaded does correct the concurrency issues, but that significantly slows down the build and the projects are still built multiple times.
This is a bug in MSBuild when referencing C++ CLI projects from multi-targeting projects. It appears they are putting in a fix to address this.
To work around the bug, the property can be removed from the reference using the GlobalPropertiesToRemove attribute:
<ProjectReference Include="..\B.CppCLILibrary\B.CppCLILibrary.vcxproj" GlobalPropertiesToRemove="TargetFramework" />
Only you could have correctly solved this since we do not have access to your code. But generally MSBuild and all build systems operate under the rule that a build 'target' is only processed once. No matter how many projects refer to it.
A build system should provide language for the user to specify dependencies between different 'targets'. And then it is up to the build system to figure out in which order to build these things in. (i.e. called a topological sort). Beginning or starting with making the most independent targets all the way to the least independent target.
If something is getting built twice it could be:
1. A bug in the build system.
2. The user forcing the project to build twice.
Anyways glad you got it sorted out.

VS project referenced from two excluded libraries

I have two versions of my application. The first one use references of library LIB_A, the second one use references of library LIB_B. (LIB_A and LIB_B are in fact to versions of the same product, but they differ from each other, even namespaces are different.There can't be installed two versions in the one machine on the same time).
Sourcecodes of my application in both versions are almost the same so I need to have one solution, that can switch which library to use.
How can I do that?
Since you specified VS2010 in your comment, I'm adding this answer separately, so that users of VS2015 can refer to the other answer, which is a lot cleaner.
In VS2010, you can use source code sharing between the two projects. Let's say that you have created AppA, which is the app project that references LibA, and contains all the sources for the app.
You can create an app project, AppB, that references LibB. It also shares all the sources of AppA. This can be done in one of two ways:
Linking All Sources Manually
In AppB, you can create the same folder structure (if any) as AppA. Right click each subfolder and click Add->Existing Item... Navigate to the corresponding folder of AppA and select all the C# files. Now click on the dropdown to the right of the Add button and select "Add as Link". You'll notice that the added sources have a little "shared" arrow in their icons, and that their paths point back to the original.
Linking All Sources Dynamically
If you have lots of files in AppA, or add/remove files regularly, the previous approach can get tiring. There's another way to do this that involves hand-editing AppB.csproj. Open AppB.csproj and create an ItemGroup that imports all the files from AppA. This code assumes that AppA and AppB are subfolders of the solution folder. If not, change the relative paths appropriately.
<ItemGroup>
<Compile Include="..\AppA\\**\*.cs">
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
</ItemGroup>
Now when you open the solution, you will see that AppB's contents match that of AppA. The sources are linked, so AppB's conditional build settings (if any) will apply.
You can also exclude files from being included by adding an Exclude attribute to the Compile tag. See the VS documentation for more details.
The only downside of this approach is that you need to hand-edit the csproj file. Also, if you accidentally delete or move linked files, VS will hard-code the list of linked files into the project. The files themselves will still be linked.
It so happens that Visual Studio 2015 (you can download the Release Candidate, which I've found much more powerful and faster than VS2013) has a feature that is designed for this very purpose - Shared Projects. Here's a Channel9 video that describes it.
A shared project contains source files that are compiled directly into projects that reference it. Let's say a shared project Shared has a file foo.cs, and projects AppA and AppB both reference project Shared, then file foo.cs is compiled directly into AppA and AppB - it uses any conditional settings of those projects. So foo.cs could have code that looks like this
#if APPA
// do something
#elif APPB
// do something else
#endif
So to summarize:
Within a single solution, create a Shared Project with all your app sources.
Create two projects AppA and AppB, that represent the two flavors of your app.
AppA references Shared and Lib_A. AppB references Shared and Lib_B.
If needed, add compile variables that control differences in the sources as described above.

Suppress warning on solution level. Treat warning as error on solution level

I am trying to set global rules for my team. We are using VS2012 with TFS for our C# projects. I'd like to suppress some of the warnings and also treat some of the warnings as errors. I found the way to do it on the project level - project properties -> build tab.
But we have solution with more than hundred projects and I am looking for some easier way to set those rules globally.
A solution is just a (pretty dumb) container for projects. If you open it in a text editor you'll quickly see you can't extend it, only add projects/items.
What you want is one or more common msbuild files specifying all needed options for compiler/linker/whatever tools you use, and Import it in every single project. We've been using this for years and it's very convenient (though part of the convenience is probably we also wrote a small tool to generate project files to automatically import the global properties so we don't have to mess with them manually)
Alternatively you could add a machine wide file, look in $(MSBuildToolsPath)\Microsoft.CSharp.targets to see where to place those files. I'm not going to copy/paste the content here, but the very first lines basically check if there are user definded files in eg $(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\$(MSBuildThisFile)\ImportBefore and if so they're all imported before all common msbuild stuff. Likewise the end of the Microsoft.CSharp.targets contains similar logic to import files after all common msbuild stuff.
As of MSBuild 15 (circa 2017) you can use Directory.Build.Props file in the top folder of your solution. The syntax is the same as csproj, fsproj, or vbproj file and the entries are treated as though they are injected into all project files. You will need to restart Visual Studio to apply the changes. (thanks Jumbo!)
<Project>
<PropertyGroup>
<WarningsAsErrors>CS4014, CS1998</WarningsAsErrors>
</PropertyGroup>
</Project>

How do I fix a corrupted build manager in vs2010?

I have a C# project in vs2010 that has several build options (Debug, Release, Debug x86, Debug I Just Got A New Hat, etc), because some people have gone a bit overboard in adding projects.
I want to revert all of that to just the four basic build types:
debug x86
release x86
debug x64
release x64
I remove a project, save the sln with that project apparently no longer in the solution, and then add it back, but apparently the settings for the project have been saved. Is there any way to remove these extraneous projects entirely from the build manager and start from scratch short of creating a new SLN file?
The impetus for fixing this problem is that one of the projects in the solution won't allow for an x64 build to be made. If I try to create an x64 build for that project, the build manager states that the x64 build already exists, even when though clearly does not. The build manager isn't allowing me to remove build modes, just add them, but then it doesn't let me add the x64, which is what I'm needing.
Quickest way is to manually edit the .proj files in notepad, removing all the
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'NewHat|x64' ">...</PropertyGroup>
elements for each configuration. Then finally remove the unwanted solution configurations by again editing the .sln file in notepad. They are easy to spot.
Once removed, you should be able to open up the solution in VS and set things right in the configuration manager
The alternatives are to use a macro or VS EnvDTE classes to automate the process but that's perhaps the sledgehammer for a nut.
Normally I don't recommend doing this but you may need to take Notepad or your favourite XML editor and change the contents of your csproj file. The reason I don't like to recommend this approach is that if you get the editing wrong you can end up with a broken project.
Obviously you should back everything up before you start so you can at least get back to your current state if everything goes pear shaped.
Ideally you can dig into your Source Code Control system and get a copy of the csproj file from back when it wasn't broken and use that as a rough guide to what a well formed csproj file for your project looks like.
You can also create a completely new C# project using the same template as your project and use that project's csproj file as another guide to what things should look like.
If you're lucky your csproj file will contain a number of PropertyGroup items, some of which will have a condition identifying the particular build combination the group applies to. For example...
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
If you delete the groups for configurations you no longer want and delete any that seem to apply to x64 you may find that the build manager will let you add an x64 configuration.

Categories