C# VS项目引用因GUID区分大小写而断开

C# VS项目引用因GUID区分大小写而断开,c#,visual-studio,visual-studio-2015,intellisense,roslyn-code-analysis,C#,Visual Studio,Visual Studio 2015,Intellisense,Roslyn Code Analysis,自从升级到VS 2015后,我的团队经历了随机的怪事,我确信微软现在正在解决这些怪事。一个相当恼人的问题是,我们似乎丢失了项目引用,尤其是在分支之后。昨天我开始研究解决方案的一个新分支,结果发现类型无法识别,名称空间使用被认为是不必要的(因为它们用于突然变得无法识别的类型) 项目中的引用没有显示任何表示引用有问题的图标,只是为了看看它是否有效,我删除并重新添加了一个项目引用,这使得它的类型再次被识别 当然,这更新了项目文件,所以我查看了所做的更改。无法检测到引用的项目与现在可以检测到的项目之间的

自从升级到VS 2015后,我的团队经历了随机的怪事,我确信微软现在正在解决这些怪事。一个相当恼人的问题是,我们似乎丢失了项目引用,尤其是在分支之后。昨天我开始研究解决方案的一个新分支,结果发现类型无法识别,名称空间使用被认为是不必要的(因为它们用于突然变得无法识别的类型)

项目中的引用没有显示任何表示引用有问题的图标,只是为了看看它是否有效,我删除并重新添加了一个项目引用,这使得它的类型再次被识别

当然,这更新了项目文件,所以我查看了所做的更改。无法检测到引用的项目与现在可以检测到的项目之间的唯一区别是GUID中的字母字符已从小写改为大写。例如:

旧的、断开的引用:

<ProjectReference Include="path/redacted">
    <Project>{95d34b2e-2ceb-499e-ab9e-b644b0af710d}</Project>
    <Name>Project.Name.Redacted</Name>
</ProjectReference>
<ProjectReference Include="path/redacted">
    <Project>{95D34B2E-2CEB-499E-AB9E-B644B0AF710D}</Project>
    <Name>Project.Name.Redacted</Name>
</ProjectReference>

{95d34b2e-2ceb-499e-ab9e-b644b0af710d}
Project.Name.redated
新的固定参考:

<ProjectReference Include="path/redacted">
    <Project>{95d34b2e-2ceb-499e-ab9e-b644b0af710d}</Project>
    <Name>Project.Name.Redacted</Name>
</ProjectReference>
<ProjectReference Include="path/redacted">
    <Project>{95D34B2E-2CEB-499E-AB9E-B644B0AF710D}</Project>
    <Name>Project.Name.Redacted</Name>
</ProjectReference>

{95D34B2E-2CEB-499E-AB9E-B644B0AF710D}
Project.Name.redated
我正在寻找发生这种情况的原因,以及如何在不必手动删除和重新添加所有引用(也不必将所有项目文件guid转换为大写)的情况下修复它


我应该注意到,这些“断开的”引用并没有断开构建,它们只在错误列表中显示为IntelliSense错误,而不是构建错误。所以,这些引用并不是真的被破坏了,它们只是破坏了IntelliSense(可以说是更糟的?!)。

项目系统中似乎有一个bug。此powershell将在项目上循环并使所有引用大写:

#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
}
这太简单了。如果您在项目中依赖guid而不是引用,那么您可能希望将其转化为更智能的东西。

TL;DR

VisualStudio在如何为项目分配GUID或如何在项目引用中指定这些GUID方面并不完全一致。我能够通过为
ProjectGuid
元素使用带大括号的大写guid和为
Project
元素使用带大括号的小写guid(在参考资料中)来解决这个问题

背景

我们有一个大型解决方案(60+C#项目),并且在解决方案重建方面经常出现问题,因为不正确的构建顺序会导致无法解决尚未构建(但本应构建)的引用项目。生成依赖项和生成顺序似乎正确。MSBuild批生成工作正常,只是从Visual Studio重建时出现问题

强制所有项目GUID使用大括号大写,所有项目引用GUID使用大括号小写,修复了该问题。VisualStudio通常是这样生成这些GUI的,但并不总是这样

在一种全新的测试溶液中进行一些调查,结果表明:

  • 为控制台应用程序项目生成的guid是带大括号的大写
  • 为类库项目生成的guid最初是小写的,没有大括号
  • 如果将新项目引用添加到具有小写GUID的类库项目中,则不仅会添加引用GUID,还会将项目GUID转换为带大括号的大写
  • 如果制作了类库项目的副本,然后将其添加到解决方案中,则其GUID将替换为使用大写和大括号的新GUID。(但是,如果制作了副本并且手动删除了其GUID,则Visual Studio不会将替换GUID插入到.csproj文件中。)
  • 项目引用GUID通常使用小写和大括号,但不知何故,我们的项目积累了大量大写GUID引用
  • .sln中的GUID始终使用大写和大括号
  • 我能够通过用全大写或全小写替换引用GUID来修复损坏的重建--这是由于大写和小写的混合导致Visual Studio出现问题(可能是某个字典中区分大小写的字符串键?),因为Visual Studio通常使用小写GUI添加引用,这是我选择的选择

    正则表达式搜索和替换

    为了解决这个问题,我使用了基于Notepad++regex的搜索和替换in文件,强制.csproj文件中的所有projectguid都使用大括号大写(控制台应用程序的默认值,并且在向项目添加任何项目引用后,Visual Studio将应用样式):

    查找内容:()\{?([0-9a-f-]+)\}()
    替换为:\1{\U\2}\E\3
    搜索:*.csproj
    
    确保打开正则表达式搜索,并关闭匹配大小写。不要搜索所有文件,否则您可能会做出不想要的更改,例如在*.xproj文件中,正如@AspNyc所指出的那样。(有关使用正则表达式更改大小写的更多信息,请参见。)

    然后,我用大括号替换了对项目的所有引用,以使用小写(这是Visual Studio通常所做的):

    查找内容:()\{?([0-9a-f-]+)\}()
    替换为:\1{\L\2}\E\3
    搜索:*.csproj
    

    完成这些更改后,Visual Studio解决方案重建现在可以可靠地工作。(至少在下一次rogue大写引用GUID潜入我们的项目之前是这样。)

    为了在git钩子中使用答案,我必须将其转换为sed的正则表达式语法:

    sed -r "s/(<Project>\{?)([0-9A-F-]+)(\}?<\/Project>)/\1\L\2\E\3/g" sample.csproj
    
    sed-r“s/(\{?)([0-9A-F-]+)(\}?)/\1\L\2\E\3/g”sample.csproj
    

    可能有人觉得这很有用。

    我在将VS2017 v15.7升级到v15.9时遇到了类似的问题


    对我来说,答案是关闭VS,清除解决方案根目录中隐藏的
    .VS
    文件夹,然后重新启动VS。

    今天在visual studio 2019(16.2.2)中,我遇到了构建系统问题,其中项目是不必要的
    $datenow = get-date
    
    $files = Get-ChildItem -path "C:\Data\Workspaces\LumberTrack\" -recurse | where { $_.PSIsContainer -eq $false} 
    
    foreach ($file in $files)
    {
    if ($file.Extension -eq ".csproj") 
    {
       Set-ItemProperty $file.FullName LastWriteTime $datenow
       Write-Output $file.FullName
    }    
    }    
    }