Ссылки на проекты VS не работают с учетом регистра 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 (что, возможно, еще хуже?!).


person bubbleking    schedule 24.03.2016    source источник
comment
У меня тоже была эта проблема... Поиск регулярных выражений с небольшим количеством powershell творит чудеса... Я связался с командой продукта, чтобы узнать, есть ли обходной путь.   -  person jessehouwing    schedule 24.03.2016
comment
@jessehouwing - Wowzers, как можно пинговать команду разработчиков? У вас случайно не осталось вашего регулярного выражения и PS-скрипта, не так ли?   -  person bubbleking    schedule 24.03.2016
comment
Встреча со многими из них лично и получение статуса MVP имеет свои преимущества :). Нет, у меня нет PowerShell под рукой... Формат для Guid достаточно однообразен :) метод перевода в верхний регистр довольно прост ;).   -  person jessehouwing    schedule 24.03.2016
comment
Пингую их снова. Последний ответ: Спасибо за отчет — я не знал об этой проблеме, но мы посмотрим.   -  person jessehouwing    schedule 04.04.2016
comment
Я не думаю, что это вполне представляет собой ответ, но я решил свою проблему. После полного удаления решения из моей системы и повторного получения его из системы управления версиями проблема не исчезла. Однако позже, просто чтобы быть уверенным, я проделал тот же процесс еще раз, и это исправило его. О, тайны Visual Studio.   -  person bubbleking    schedule 04.04.2016
comment
Эта ошибка все еще присутствует в Visual Studio 2015 Update 3.   -  person Nick    schedule 07.02.2017
comment
У нас также есть эта проблема в VS 2015, обновление 3. И это вызывает сбои при перестроении решения для нашего большого решения (60+ проектов). Пакетные сборки с использованием MSBuild прекрасны, только при перестройке из Visual Studio у нас возникает проблема, которую решает использование верхнего регистра ссылок.   -  person yoyo    schedule 22.02.2017
comment
Странно: мне пришлось преобразовать альфа-символы в ссылке на проект в файле csproj в нижний регистр, чтобы заставить сборку VS работать...   -  person Bernhard Hiller    schedule 03.05.2017
comment
Я столкнулся с этой проблемой, за исключением того, что мой коллега мог построить точно такую ​​же ветку, а я не смог. Я удалил свой файл *.suo из папки .vs решения, и это решило проблему для меня, позволив мне создать решение. Это, вероятно, объясняет, почему MSBuild не затрагивается, но почему пользовательские настройки решения вызывают проблему с чувствительностью к регистру...   -  person Nick    schedule 28.09.2017
comment
VS 2017, ошибка все еще жива и работает. Возможно, в VS 2019 это будет решено :)   -  person ebol2000    schedule 10.04.2019


Ответы (5)


TL;DR

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

Фон

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

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

Проведя небольшое исследование в совершенно новом тестовом решении, оказалось, что:

  1. Генерируемые идентификаторы GUID для проектов консольных приложений указываются в верхнем регистре с фигурными скобками.
  2. Сгенерированные идентификаторы GUID для проектов библиотеки классов изначально имеют строчные буквы без фигурных скобок.
  3. Если в новую ссылку на проект добавляется проект библиотеки классов с GUID в нижнем регистре, то не только добавляется GUID ссылки, но и GUID проекта преобразуется в верхний регистр с фигурными скобками.
  4. Если создается копия проекта библиотеки классов, а затем добавляется в решение, ее идентификатор GUID заменяется новым, в котором используются прописные буквы и фигурные скобки. (Но если сделана копия и ее GUID удален вручную, Visual Studio не вставит новый GUID в файл .csproj.)
  5. Ссылки на проекты GUID обычно используют строчные буквы и фигурные скобки, но каким-то образом наш проект накопил кучу ссылок GUID в верхнем регистре.
  6. GUID в .sln всегда используют верхний регистр и фигурные скобки.

Я смог исправить нашу неработающую перестройку, заменив ссылочные 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. (Дополнительную информацию об использовании регулярных выражений для изменения регистра см. в этом ответе.)

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

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

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

person yoyo    schedule 22.02.2017
comment
Я скоро рассмотрю подробности, но хотел бы прокомментировать TL; DR - у меня нет оснований полагать, что кто-то скопировал и вставил CSPROJ в качестве шаблона, когда наша команда столкнулась с этими проблемами. - person bubbleking; 22.02.2017
comment
Хм, я тоже продолжаю работать над своим исправлением. Я только что заметил, что когда ссылка добавляется в проект С#, ProjectGuid переключается с нижнего регистра без фигурных скобок на верхний регистр с фигурными скобками. Таким образом, все в нижнем регистре может не быть постоянным решением в конце концов. Я продолжу экспериментировать, а затем вернусь и соответствующим образом изменю свой ответ. - person yoyo; 22.02.2017
comment
Я знаю, что буду использовать это (неизбежно) в следующий раз, когда наши GUID сойдут с ума. Молодец и все получилось! - person bubbleking; 28.02.2017
comment
@bubbleking Я думаю, что это тоже решило проблемы со сборкой, которые у нас были - отличная работа! Одно замечание: вы можете ограничить поиск/замену файлами *.csproj. Причина в том, что файлы *.xproj — файлы проекта .NET Core — используют GUIDS без начальных или фигурных скобок. Поэтому, когда я попробовал ваше опубликованное решение, оно также добавило фигурные скобки там, где их раньше не было. - person Mass Dot Net; 11.03.2017
comment
@AspNyc, да, я конвертировал только файлы *.csproj. Я сказал в файлах .csproj, но я мог бы более четко указать параметры «Найти и заменить», извините. - person yoyo; 06.04.2017
comment
@yoyo Не за что извиняться - ваш пост помог решить некоторые действительно разочаровывающие проблемы со сборкой, которые я видел! Я просто хотел поделиться тем, на что я наткнулся изначально, чтобы немного прояснить ситуацию. - person Mass Dot Net; 25.05.2017

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

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

person Slappywag    schedule 07.01.2019
comment
Только что это появилось и в VS2017 v15.8. В нашем случае удаление и повторная ссылка на проект добавили Guid обратно в нижнем регистре. Ваше исправление сработало, и в настоящее время мы обновляем его до версии 15.9. - person KingCronus; 28.01.2019
comment
Спасибо, это помогает и для VS 2017 Professional 15.9.13. - person v.slobodzian; 19.07.2019

Кажется, в системе проектов есть ошибка. Этот 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
}

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

person jessehouwing    schedule 04.04.2016
comment
Поскольку я уже исправил свою проблему, я проверил это, создав несколько фиктивных текстовых файлов с расширениями .csproj, .vbproj и .sln. Затем я сохранил немного lorem ipsum вместе с несколькими идентификаторами GUID в каждый файл и запустил этот скрипт в каталоге. В результате содержимое файлов было полностью стерто. Есть ли что-то в моем способе тестирования, что могло бы вызвать это? - person bubbleking; 04.04.2016
comment
Возможно, это я включил запись имени файла. PS делает странные вещи, когда методы записывают вывод... - person jessehouwing; 04.04.2016
comment
Мы надеемся, что они исправили эту ошибку в VS15 Update 2! - person bubbleking; 08.06.2016
comment
Мы надеемся, что они исправят эту ошибку в VS15 Update 4! - person yoyo; 22.02.2017
comment
Сделайте это Visual Studio 2017. Я не буду ожидать обновления 4 на 2015 год. - person jessehouwing; 22.02.2017
comment
Этот скрипт сделал мои файлы проекта нечитаемыми... и все в одной строке - person steve; 04.12.2018
comment
Вы можете указать флаг -Raw для gc, чтобы вернуть строку вместо массива строк, и тогда не должно быть однострочных файлов. - person dumbchemistry; 30.09.2019
comment
Пришлось добавить кодировку Out-File $_.FullName -Encoding "UTF8". В противном случае я получил ошибку: '.' шестнадцатеричное значение 0x00 является недопустимым символом. строка 2 позиция 1 - person r2d2; 29.07.2020

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

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

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

person C. Göbeler    schedule 03.04.2018

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

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

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

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

Если кому-то это будет полезно, ниже приведен 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
}    
}    
}    
person David Beavon    schedule 26.08.2019
comment
Вау, спасибо, что поделились этим; сценарий особенно полезен. Если у вас есть доступ к ReSharper, я также рекомендую попробовать их инструмент сборки. Предположительно, он лучше анализирует, какие проекты действительно нуждаются в перестройке, тем самым экономя время. Возможно, и в этом случае его результаты были бы лучше. - person bubbleking; 26.08.2019