Общесистемное событие предварительной сборки?



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



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

680   6  

6 ответов:

необычное требование. Но это можно сделать. Добавьте новый проект в решение, используя шаблон проекта Visual C++ > General > Makefile. Задайте его помощью nmake > командную строку Параметр команды, которые вы хотите выполнить. Используйте проект > зависимости проекта, чтобы все остальные проекты зависели от него.

краткий обзор моих вариантов ниже

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

summary

Примечания:

  • 1 - не требует никаких дополнительных расширений. Но он может работать только на уровне проектов, поэтому мы используем его для эмуляции нашего уровня решения... Оно тяжело и неудобно для общего решения, но есть вариант. Увидеть ниже.
  • 2 - оригинальный движок vsSolutionBuildEvent предоставляет несколько способов унифицированной поддержки VS и msbuild.исполняемый. Простой способ targets mode вызов after.<name>.sln.targets это доступно только для msbuild.exe (это не требует дополнительных шагов, просто действия). Но только оригинальный двигатель (inc. vsCommandEvent) может разрешить дополнительные сценарии, которые поддерживают, например (7zip архиватор, упаковка пакета nuget без nuget.ехе, удаленных серверов и т. д.). Однако это не важно для нашего вопроса / проблемы, и вы можете использовать любую доступную опцию для поддержки уровня решения, если вы видите + выше.

Вариант 1: Microsoft.VisualStudio.Ракушка.Взаимодействие

этот вариант не для простых пользователей против. Однако он может быть полезным для полного решения и т. д.

вы должны реализовать, для пример:

например:

public sealed class YourPackage: Package, IVsSolutionEvents, IVsUpdateSolutionEvents2
{
...
    public int UpdateSolution_Begin(ref int pfCancelUpdate)
    {
        //TODO:
    }
}

затем зарегистрируйте обработчик с помощью методов' Advise ' в качестве приоритетного слушателя, т. е. для IVsUpdateSolutionEvents2 вы должны использовать AdviseUpdateSolutionEvents

важно, потому что BuildEvents (см. EnvDTE) - наверное, не поможет и может работать слишком поздно - пример

образец с 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);

где:

  • the sbm поле должно быть частью класса для защиты от GC.
  • чтобы получить службу SVsSolutionBuildManager используется ServiceProvider, но это может быть так, как вам нужно. Видеть msdn

теперь мы можем работать со всеми проектами сразу-на уровне решения.

Вариант 2: Цели и карта проектов.

ок, вы любите что-то вроде этого - MSBuild: расширение сборки решения, но этот вариант может работать с процессами сборки из msbuild.exe, а не от VS IDE...

но VS также использует цели (Build, Rebuild, Clean,..) в файлах проекта (*.csproj,*.vcxproj, ..) когда начата сборка-операции. Так что мы тоже можем попробовать это, но помните:

  • ВС также игнорирует удивительно .sln файл. Он формирует все конечные цели из загруженной среды с помощью EnvDTE и т. д.
  • The .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, значит).

и так, если вам нужно общее решение (т. е. вы можете не знать, о проектах и т. д. - это может быть, например, для некоторых решений и похожие):

  • добавить вашу общую .целевой файл во все ваши проекты (это может быть автоматически с любым инструментом, inc. элемент события NuGet etc.) , например: <Import Project="..\<SolutionFile>.targets" />
  • затем, вы должны использовать некоторые ограничения для:
    • "только-перед всеми проектами"
    • только" - после всех проектов"

и например, да, это может быть карта проекты':

  • The карта проектов' иллюстрирует решения событий ДО/ПОСЛЕ для сборки-операции с Visual Studio интегрированная среда разработки (т. е. основной среды разработки vs)
...
<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> Раздел для новых проектов в первом в этом. Это действительно неудобно, но тоже вариант...

Вариант 3: плагин vsSolutionBuildEvent

на сегодняшний день это наиболее полное решение для работы с большим количеством событий в качестве Events-Catcher с различными расширенными действиями для обслуживания ваших проектов и библиотек, построения процессов и процессов во время выполнения из вашей Visual Studio и MSBuild Tool.

различные типы действий для всех подпроектов сразу в решении как решение-события или индивидуально для каждого.

https://visualstudiogallery.msdn.microsoft.com/0d1dbfd7-ed8a-40af-ae39-281bfeca2334/

plugin - vsSolutionBuildEvent

как это работает внутри

если вы хотите использовать Вариант 1 выше или нужно посмотреть, как работать с оболочкой.Взаимодействия, автоматизации EnvDTE, IVsUpdateSolutionEvents2 в MSBuild двигателя и т. д., видеть здесь:

scheme

Вариант 4. EnvDTE.CommandEvents

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

это не то же самое, Но да, это также возможно с 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/doc/Features/Solution-wide/

кроме того, необязательно вы можете подавить эти команды, если вам нужно. в варианте ниже вы увидите полное решение для этого путь.

Вариант 5. Плагин vsCommandEvent

https://visualstudiogallery.msdn.microsoft.com/ad9f19b2-04c0-46fe-9637-9a52ce4ca661/

он также представляет расширенный обработчик большинства событий, но в отличие от первого он специализируется на MS Visual Studio для расширенной работы со всеми командами и выходными данными в качестве менеджера этого. Не только для проектов и решений, но и для всей среды разработки Visual studio.

В общем, это общее решение Вариант 4 и вы можете просто переопределить все команды выше, чтобы решить эту проблему.

и для той же модели событий-действий, как в vsSolutionBuildEvent это может быть полезно в большинстве случаев.

scheme

"помогите мне с вариантами"

есть открытая реализация для всех этих вариантов. Смотрите здесь и улыбнись:

вы можете взглянуть на эту статью: MSBuild: расширение сборки решения.

кажется, именно то, что вам нужно.

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

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

еще один старый пост, но вдохновленный решением @reg я хотел запустить простой таймер сборки, который будет регистрировать прошедшее время для сборки решения. Я получил события сборки, работающие с помощью модуля powershell,который я загружаю через консоль диспетчера пакетов при запуске Visual Studio IDE.

так что создайте модуль powershell, как BuildEvents.psm1:

<#
.SYNOPSIS
    Register solution build events

.DESCRIPTION
    Registers the OnBuildBegin and OnBuildDone events for the entire solution
    De-registers the events if called multiple times.

.EXAMPLE
    RegisterBuildEvents
#>
function RegisterBuildEvents{
  try {
    Unregister-Event -SourceIdentifier "OnBuildBegin" -Force
  } catch {
    #we don't care if this doesn't work
  }
  try {
    Unregister-Event -SourceIdentifier "OnBuildDone" -Force
  } catch {
    #we don't care if this doesn't work
  }
  $obj = [System.Runtime.InteropServices.Marshal]::CreateWrapperOfType($dte.Application.Events.BuildEvents, [EnvDTE.BuildEventsClass])
  Register-ObjectEvent -InputObject $obj -EventName OnBuildBegin -Action {
    # do stuff here on build begin
    Write-Host "Solution build started!"
  } -SourceIdentifier "OnBuildBegin"
  Register-ObjectEvent -InputObject $obj -EventName OnBuildDone -Action {
    # do stuff here on build done
    Write-Host "Solution build done!" 
  } -SourceIdentifier "OnBuildDone"
}

# export the functions from the module
export-modulemember -function RegisterBuildEvents

импорт модуля при инициализации узла диспетчера пакетов:

  1. в типе консоли диспетчера пакетов $профиль, чтобы получить расположение вашего профиля powershell
  2. перейдите в этот каталог на диске, если там нет файла создать один с именем, возвращенным вышеуказанной командой (например NuGet_profile.ps1)
  3. открыть файл в блокноте и добавьте следующие строки

    Import-Module -Name <Path to your ps module>\BuildEvents -Force
    RegisterBuildEvents
    

Comments

    Ничего не найдено.