Be Careful When Copying Visual Studio Projects
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:
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
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
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:
ClassLibrary2reference properties for
ConsoleApplication2project will incorrectly point to
ClassLibrary1, although it will still show up as
ClassLibrary2in 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.
The Project Dependencies window will also incorrectly show
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
ClassLibrary2, creating a circular dependency. The new build order will cause
ClassLibrary2to be built before
ConsoleApplication2, although the latter requires the former for the build to succeed, hence the build will fail.
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.