VS Project References Broken On Case Sensitivity of GUID

I suffered a similar issue when updating VS2017 v15.7 to v15.9.

The answer for me was to close down VS, clear out the hidden .vs folder in my solution's root directory and restart VS.


TL;DR

Visual Studio isn't entirely consistent about how it assigns GUIDs to projects or how it specifies those GUIDs in project references. I was able to resolve the problem by using upper case GUIDs with braces for ProjectGuid elements and lower case with braces for Project elements (in references).

Background

We have a large solution (60+ C# projects), and were having regular issues with solution Rebuild as incorrect build order would cause failure to resolve referenced projects that had not yet been built (but should have been). Build Dependencies and Build Order appeared correct. MSBuild batch build worked fine, it was only a problem when rebuilding from Visual Studio.

Forcing all project GUIDs to upper case with braces and all project reference GUIDs to lower case with braces fixed the problem. This is usually how Visual Studio generates these GUIDs, but not always.

Doing some investigation in a brand new test solution, it turns out that:

  1. Generated GUIDs for console application projects are upper case with braces.
  2. Generated GUIDs for class library projects are initially lower case with no braces.
  3. If a new project reference is added a class library project with a lower case GUID, then not only is the reference GUID added, but the project GUID is converted to upper case with braces.
  4. If a copy of a class library project is made and then added to the solution then its GUID is replaced with a new one that uses upper case and braces. (But if a copy is made and its GUID manually removed, Visual Studio does not insert a replacement GUID into the .csproj file.)
  5. Project references GUIDs are usually use lower case and braces, but somehow our project had accumulated a bunch of upper case GUID references.
  6. GUIDs in the .sln always use upper case and braces.

I was able to fix our broken rebuild by replacing the reference GUIDs with either all upper case or all lower case -- it's something about the mix of upper and lower case that was giving Visual Studio problems (perhaps case-sensitive string keys in a dictionary somewhere?) Since Visual Studio normally adds references with lower case GUIDs, that is the option I chose to go with.

Regex Search & Replace

To fix this, I used Notepad++ regex-based search and replace in files to force all ProjectGuids in .csproj files to be upper case with braces (the default for console applications, and the style Visual Studio will apply after adding any project reference to the project):

Find what: (<ProjectGuid>)\{?([0-9a-f-]+)\}?(</ProjectGuid>)
Replace with: \1{\U\2}\E\3
Search in: *.csproj

Be sure to turn on regular expression search, and turn off match case. And don't search all files, or you may make changes you don't want, for example in *.xproj files, as noted by @AspNyc. (See this answer for additional info on use of regular expressions for changing case.)

I then replaced all references to projects to use lower case with braces (which is what Visual Studio usually does):

Find what: (<Project>)\{?([0-9a-f-]+)\}?(</Project>)
Replace with: \1{\L\2}\E\3
Search in: *.csproj

Having made these changes, Visual Studio solution rebuild now works reliably. (At least until next time rogue upper case reference GUIDs sneak into our project.)


There's a bug in the projectsystem it seems. This powershell will loop over projects and make all references upper case:

#FixGuids

get-childitem -recurse | ?{ @('.sln', '.csproj', '.vbproj') -contains $_.Extension } | %{
   [regex]::Replace((gc -raw $_.FullName), '[{(]?[0-9A-Fa-f]{8}[-]?([0-9A-Fa-f]{4}[-]?){3}[0-9A-Fa-f]{12}[)}]?', { return ([string]$args[0]).ToUpperInvariant() }) |
      Out-File $_.FullName -Encoding "UTF8
}

It's quite simplistic. If you rely on guids in your projects for something other than references, you may want to turn it into something more intelligent.