Be Careful When Copying Visual Studio Projects

December 5th 2015 Visual Studio .NET Framework

Project GUIDs Uniquely Identify Projects

You might not be aware of it, but Visual Studio projects have additional identity beyond their project file name and path. Each one of them contains a GUID value which should by definition be unique in normal circumstances. The troubles begin, when you create a copy of a project by copying its folder and renaming the files.

Visual Studio uses project GUIDs to identify different project files and their dependencies in a solution file, as well as for references between projects inside a single solution file. For this to work, it needs all project GUIDs to be unique inside a solution file. When you add an existing project to the solution file, it verifies its project GUID and modifies it, if there is already a project with the same GUID in the solution. In simple scenarios this is enough to ensure consistency. If the same project is included in multiple solutions, Visual Studio might start to misbehave.

Making Visual Studio Confused

We'll start by creating 2 different solutions, each one containing a console application, referencing a class library:

Initial project dependencies

Instead of creating ClassLibrary2 as a new project in Visual Studio, we will copy and rename ClassLibrary1, and add it to the second solution. Although this will cause ClassLibrary1 and ClassLibrary2 to have the same project GUID, Visual Studio will keep them unchanged and won't complain because inside each solution the two projects have distinct project GUIDs.

In the next step we will add ClassLibrary2 to the first solution and also add it as a reference to ConsoleApplication1:

ConsoleApplication1 now references ClassLibrary2

This will already cause an inconsistency: the first solution will change the project GUID for ClassLibrary2 and use the new value in both the solution file and the ConsoleApplication1 project file to reference the library. ConsoleApplication2 will keep referencing the same library using its old project GUID. As a consequence the project GUID in the ClassLibrary2 project file will keep changing, depending on the last solution it was open with. Still, apart from phantom changes in source control, no other issues will arise yet.

To make matters worse, we can add ConsoleApplication2 to the first solution as well. This will brake Visual Studio in several ways:

  • The ClassLibrary2 reference properties for ConsoleApplication2 project will incorrectly point to ClassLibrary1, although it will still show up as ClassLibrary2 in Solution Explorer. Obviously this functionality depends on the project GUID values. Fortunately this doesn't affect the build. MSBuild depends on filenames and still works correctly.

    Project reference in Solution Explorer and its properties

  • The Project Dependencies window will also incorrectly show ConsoleApplication2 depending on ClassLibrary1 instead on ClassLibrary2. Since this information is used to define the project build order and restrict adding of project references in order to prevent circular dependencies, the consequences are quite dire. E.g. I can add a reference to ConsoleApplication2 from ClassLibrary2, creating a circular dependency. The new build order will cause ClassLibrary2 to be built before ConsoleApplication2, although the latter requires the former for the build to succeed, hence the build will fail.

    Incorrect information in Project Dependencies window

Avoid Duplicate Project GUIDs

I am aware that this a contrived example that could hardly happen in a real life scenario. However, when a team is working on a product consisting of dozens or even hundreds of projects, included in multiple different solution files for different development tasks, such situations can actually occur, if creating similar projects by copying existing ones becomes a habit. Trust me, I have encountered it. Troubleshooting wasn't easy and took some time.

Therefore, if you have a requirement for creating multiple similar projects, make sure you prevent duplicate project GUIDs from the start:

  • I recommend you create a dedicated project template and distribute it to your developers. In simple scenarios the Export Template wizard can be all you need.
  • Alternatively, you can create a new project based on one of Visual Studio built-in templates, followed by copying your specific files into it and including it in the project.
  • If you still think, you need to copy the projects, you should add the copied project to the solution containing the original project and at least temporarily reference it from one of the other projects. This will ensure that the copied project will get a new unique project GUID value.

Having discipline from the start can save you a lot of time in the long run.

Copyright
Creative Commons License