Подтвердить что ты не робот

Ссылки на VS-проект Broken On Case Чувствительность GUID

Начиная с обновления до VS 2015, моя команда испытала случайные причудливые вещи, которые, я уверен, сейчас разрабатываются в Microsoft. Один из нас очень раздражает то, что мы, похоже, теряем проектные ссылки, особенно после разветвления. Вчера я начал работать над новой ветвью нашего решения, чтобы узнать, что типы были непризнаны, а имена пространства имен считаются ненужными (потому что они были для типов, которые внезапно стали непризнанными).

В ссылках в проекте не отображаются значки, указывающие на проблему с ссылкой, но чтобы убедиться, что это сработает, я удалил и повторно добавил ссылку на проект, что привело к тому, что его типы были распознаны еще раз.

Это, конечно, обновило файл проекта, поэтому я посмотрел, какие изменения были внесены. Единственное различие между проектом, который не смог обнаружить ссылку, и тот, который теперь может, состоит в том, что альфа-символы в 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>

Я ищу причину, по которой это происходит, и как я могу ее исправить без необходимости вручную удалять и повторно добавлять ссылки повсюду (и без необходимости конвертировать все идентификаторы GUID проекта в верхний регистр).

Я должен отметить, что эти "сломанные" ссылки не нарушают сборку и что они отображаются только в списке ошибок как ошибка IntelliSense, а не строят ошибки. Итак, ссылки на самом деле не сломаны, они только что сломали IntelliSense (что, возможно, хуже?!).

4b9b3361

Ответ 1

TL; DR

Visual Studio не совсем согласуется с тем, как он присваивает GUID проектам или как он определяет эти GUID в ссылках на проекты. Я смог решить проблему, используя GUID верхнего регистра с фигурными скобками для элементов ProjectGuid и нижний регистр с фигурными скобками для элементов Project (в ссылках).

Фон

У нас есть большое решение (60+ проектов на С#), и у него были регулярные проблемы с решением Rebuild, поскольку неправильный порядок сборки может привести к отказу в разрешенных проектах, которые еще не были созданы (но должны были быть). Построение зависимостей и порядок сборки оказались правильными. MSBuild batch build работал нормально, это была проблема только при перестройке из Visual Studio.

Принуждение всех GUID проекта к верхнему регистру с фигурными скобками, а все идентификаторы GUID проекта в нижний регистр с фигурными скобками устраняют проблему. Обычно это Visual Studio генерирует эти GUID, но не всегда.

Выполняя некоторые исследования в совершенно новом тестовом решении, получается, что:

  • Сгенерированные GUID для проектов консольных приложений - это верхний регистр с фигурными скобками.
  • Сгенерированные GUID для проектов библиотеки классов изначально представляют собой нижний регистр без привязок.
  • Если новая ссылка на проект добавлена ​​в проект библиотеки классов с нижним регистром GUID, то добавляется не только ссылочный GUID, но и GUID проекта преобразуется в верхний регистр с фигурными скобками.
  • Если создается экземпляр проекта библиотеки классов, а затем добавляется в решение, его GUID заменяется на новый, который использует верхний регистр и фигурные скобки. (Но если копия сделана и ее GUID удален вручную, Visual Studio не вставляет заменяющий GUID в файл .csproj.)
  • Ссылки на проекты GUID обычно используются в нижнем регистре и фигурных скобках, но каким-то образом наш проект собрал кучу ссылок GUID верхнего регистра.
  • GUID в .sln всегда используют верхний регистр и фигурные скобки.

Я смог исправить наш сломанный rebuild, заменив ссылочные идентификаторы GUID либо всем верхним регистром, либо всем нижним регистром - это что-то вроде сочетания верхнего и нижнего регистра, которые вызывали проблемы Visual Studio (возможно, строчные ключи с учетом регистра в словаре где-нибудь?) Поскольку Visual Studio обычно добавляет ссылки с нижестоящими GUID, это вариант, который я выбрал.

Поиск и замена регулярных выражений

Чтобы исправить это, я использовал поиск на основе регулярных выражений Notepad ++ и замену в файлах, чтобы заставить все ProjectGuids в файлах .csproj быть в верхнем регистре с фигурными скобками (по умолчанию для консольных приложений и стиль Visual Studio будет применяться после добавления какого-либо проекта ссылка на проект):

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

Обязательно включите поиск регулярных выражений и отключите пример соответствия. И не выполняйте поиск по всем файлам, или вы можете вносить изменения, которые вам не нужны, например, в *.xproj файлах, как указано @AspNyc. (См. этот ответ для получения дополнительной информации об использовании регулярных выражений для изменения case.)

Затем я заменил все ссылки на проекты на использование нижнего регистра с фигурными скобками (что обычно делает Visual Studio):

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

Сделав эти изменения, перестройка Visual Studio теперь работает надежно. (По крайней мере, до следующего раза жульничество с верхним регистром указывает на наш проект.)

Ответ 2

У меня возникла аналогичная проблема при обновлении VS2017 v15.7 до v15.9.

Для меня ответом было закрыть VS, очистить скрытую папку .vs в корневом каталоге моего решения и перезапустить VS.

Ответ 3

В системе проектов есть ошибка. Эта powershell будет зацикливаться на проектах и ​​сделать все ссылки в верхнем регистре:

#FixGuids

get-childitem -recurse | ?{ @('.sln', '.csproj', '.vbproj') -contains $_.Extension } | %{
   [regex]::Replace((gc $_.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
}

Это довольно упрощенно. Если вы полагаетесь на подсказки в своих проектах для чего-то другого, кроме ссылок, вы можете превратить его в нечто более интеллектуальное.

Ответ 4

Чтобы использовать ответ в ловушке git, мне пришлось преобразовать его в синтаксис sed regex:

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

Может быть, кто-то найдет это полезным.

Ответ 5

Сегодня в Visual Studio 2019 (16.2.2) я столкнулся с проблемами системы сборки, когда проекты излишне (и неоднократно) перестраивались всякий раз, когда я инициировал создание своего решения.

(Ни один из обычных шагов не помог разрешить проблемы со сборкой, например, удаление папки ".vs" или удаление каталогов "bin" и "obj" и т.д.).

Сначала это было связано с набором символов в руководствах, потому что я смог устранить проблему, отредактировав руководства и сохранив проект. Однако это была красная селедка... Я невольно решал проблему, изменяя временные метки всех моих файлов csproj. Система обновления выглядела намного счастливее после того, как были обновлены эти временные метки, и она перестала раздражать (постоянно пытаясь восстановить уже созданные проекты).

Расстановка символов направляющих вообще не стала проблемой. Насколько я могу судить, VS 2019 подходит как для upper-, так и для строчных букв. Они могут даже не соответствовать исходному проекту, основываясь на моих экспериментах (например, исходный исходный проект может использовать прописные буквы, а ссылки на проекты могут использовать строчные).

Если это кому-нибудь пригодится, ниже приведен PowerShell, который позволит вам настроить время записи всех файлов csproj по пути. Это будет еще один трюк, который я использую всякий раз, когда система msbuild плохо работает в visual studio.

$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
}    
}    
}