Краткий обзор моих вариантов ниже
просто примечание: это неполный список всех существующих (см. Также другие ответы и т. Д.), Я поддерживаю только мои оригинальные трюки в актуальном состоянии ...
Примечания:
- 1 - Не требует никаких дополнительных расширений. Но он может работать только на уровне проектов, поэтому мы используем его для эмуляции уровня нашего решения ... Это сложно и неудобно для общего решения, но это вариант. Смотри ниже.
- 2 - Оригинальный движок vsSolutionBuildEvent предоставляет несколько способов унифицированной поддержки VS и msbuild.exe. Простой способ
targets mode
вызвать after.<name>.sln.targets
, который доступен только для msbuild.exe (это не требует дополнительных шагов, просто действие). Но только оригинальный движок (в том числе vsCommandEvent) может разрешить дополнительные сценарии, которые поддерживают, например, (архиватор 7zip, упаковка пакета nuget без nuget.exe, удаленные серверы и т. Д.). Однако это не важно для нашего вопроса / проблемы, и вы можете использовать любую доступную опцию для поддержки уровня решения, если вы видите +
выше.
Вариант 1: Microsoft.VisualStudio.Shell.Interop
Этот вариант не для простых пользователей VS. Тем не менее, это может быть полезно для вашего полного решения и т. Д.
Вы должны реализовать, например:
например:
public sealed class YourPackage: Package, IVsSolutionEvents, IVsUpdateSolutionEvents2
{
...
public int UpdateSolution_Begin(ref int pfCancelUpdate)
{
//TODO:
}
}
Затем зарегистрируйте обработчик с помощью методов Advise в качестве приоритетного прослушивателя, т. Е. Для IVsUpdateSolutionEvents2 вы должны использовать AdviseUpdateSolutionEvents
Это важно , потому что BuildEvents (см. EnvDTE ) - вероятно, не поможет и может работать слишком поздно - Пример * +1064 *
Образец с AdviseUpdateSolutionEvents:
// http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.shell.interop.ivssolutionbuildmanager2.aspx
private IVsSolutionBuildManager2 sbm;
// http://msdn.microsoft.com/en-us/library/bb141335.aspx
private uint _sbmCookie;
...
sbm = (IVsSolutionBuildManager2)ServiceProvider.GlobalProvider.GetService(typeof(SVsSolutionBuildManager));
sbm.AdviseUpdateSolutionEvents(this, out _sbmCookie);
Где:
- поле
sbm
должно быть частью класса для защиты от GC.
- для получения службы SVsSolutionBuildManager используется ServiceProvider, но он может быть таким, как вам нужно. См MSDN
Теперь мы можем работать со всеми проектами одновременно - на уровне решения.
Вариант 2: цели и карта проектов.
хорошо, вам нравится что-то подобное - MSBuild: расширение сборки решения , но этот вариант может работать с процессами сборки из msbuild.exe, а не из VS IDE ...
Но VS также использует цели (Build, Rebuild, Clean, ..) в файлах проекта (* .csproj, * .vcxproj, ..), когда запускаются операции сборки. Так что мы можем попробовать это, но помните:
- VS также игнорирует удивительный файл .sln. Он формирует все конечные цели из загруженной среды с EnvDTE и т. Д.
- .sln должен обрабатываться msbuild.exe только как: автоматически генерировать .metaproj (в памяти по умолчанию), который содержит «что и когда» будет построено. Включая общие цели для всех проектов, если таковые существуют, например:
...
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\SolutionFile\ImportAfter\*" Condition="'$(ImportByWildcardBeforeSolution)' != 'false' and exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\SolutionFile\ImportAfter')" />
<Import Project="D:\tmp\p\after.name.sln.targets" Condition="exists('D:\tmp\p\after.name.sln.targets')" />
<Target Name="Build" />
<Target Name="Rebuild" />
<Target Name="Clean" />
<Target Name="Publish" />
- И да, .metaproj также не может быть просмотрен VS IDE.
Следовательно, для работы с общими целями из VS IDE вы можете использовать только файлы проекта с некоторыми ограничениями (без модификации / расширения VS это означает).
И так, если вам нужно общее решение (то есть вы можете не знать о проектах и т. Д. - это может быть, например, для некоторых коробочных решений и аналогичных ):
- Добавьте ваш общий файл .targets во все ваши проекты (он может быть автоматически любым инструментом, в том числе события NuGet и т. Д.), Например:
<Import Project="..\<SolutionFile>.targets" />
- Тогда вы должны использовать некоторые ограничения для:
- «только - перед всеми проектами»
- "только - после всех проектов"
И, например, да, это может быть «Карта проектов»:
- «Карта проектов» иллюстрирует «события» PRE / POST для всего процесса решения для операций сборки из Visual Studio IDE (т. Е. Первичного из VS IDE)
...
<Target Name="_Build" BeforeTargets="Build" DependsOnTargets="ProjectsMap">
<CallTarget Targets="_BuildPRE" Condition="$(ScopeDetectFirst)" />
<CallTarget Targets="_BuildPOST" Condition="$(ScopeDetectLast)" />
</Target>
<Target Name="_BuildPRE">
<!-- ... -->
</Target>
<Target Name="_BuildPOST">
<!-- ... -->
</Target>
...
В общем, мы будем использовать карту проектов, и теперь мы знаем, «что и когда» должно произойти. Это безопасно для всех или большинства случаев (изменение порядка сборки или удаление любых проектов из решения). Тем не мение! Вы должны управлять <Import>
разделом для новых проектов в первом init. Это действительно неудобно, но также вариант ...
Вариант 3: Плагин vsSolutionBuildEvent
На сегодняшний день это наиболее полное решение для работы с большим количеством событий в качестве Event-Catcher с различными расширенными действиями для обслуживания ваших проектов и библиотек, построения процессов и процессов во время выполнения из вашей Visual Studio и MSBuild Tool.
Различные типы действий для всех подпроектов одновременно в решении как Solution-Events или индивидуально для каждого.
https://visualstudiogallery.msdn.microsoft.com/0d1dbfd7-ed8a-40af-ae39-281bfeca2334/
Как это работает внутри
Если вы хотите использовать вариант 1 выше или хотите узнать, как работать с Shell.Interop, EnvDTE, IVsUpdateSolutionEvents2, MSBuild Engine и т. Д., См. здесь :
Вариант 4. EnvDTE.CommandEvents
Этот вариант также не для простых пользователей VS. Однако, что касается Variant 1 , это может быть полезно для вашего коробочного решения и т. Д.
Это не то же самое, но да, это также возможно с EnvDTE.CommandEvents , как в Вариант 1 выше.
Вы уже должны знать (см. Выше) о этом решении для приоритетной работы с текущим типом действия сборки ... Так почему бы не использовать это в качестве основного решения для текущей проблемы?
_cmdEvents.BeforeExecute += (string guid, int id, object customIn, object customOut, ref bool cancelDefault) => {
if(UnifiedTypes.Build.VSCommand.existsById(id)) {
// ... your action
}
};
Где:
Description | guid | id |In |Out|
--------------------------|---------------------------------------|-----|---|---|
Started: Build Solution |{5EFC7975-14BC-11CF-9B2B-00AA00573819} | 882 | | |
Started: Rebuild Solution |{5EFC7975-14BC-11CF-9B2B-00AA00573819} | 883 | | |
Started: Clean Solution |{5EFC7975-14BC-11CF-9B2B-00AA00573819} | 885 | | |
http://vsce.r -eg.net / документ / Свойства / Решение шириной /
Кроме того, по желанию вы можете подавить эти команды, если вам нужно. В приведенном ниже варианте вы увидите полное решение для этого пути.
Вариант 5. Плагин vsCommandEvent
https://visualstudiogallery.msdn.microsoft.com/ad9f19b2-04c0-46fe-9637-9a52ce4ca661/
Он также представляет расширенный обработчик большинства событий, но, в отличие от первого, он специализировался на MS Visual Studio для расширенной работы со всеми командами и вывода данных в качестве менеджера этого. Не только для проектов и решений, но и для всей Visual Studio IDE.
В общем, это общее решение Вариант 4 , и вы можете просто переопределить все команды выше для решения этой проблемы.
И для той же модели Event-Actions, что и в vsSolutionBuildEvent, она может быть полезна в большинстве случаев.
"Помоги мне с вариантами"
Есть открытая реализация для всех этих вариантов. Смотрите здесь и улыбайтесь :