Visual Studioには、いくつかのプロジェクトを含むソリューションがあります。どのプロジェクトが関係していて、それらが最新であるかどうかに関係なく、すべてのビルドの最初にコマンドを実行したいと思います。
基本的に、ソリューション全体のビルド前イベントに似たものが必要ですが、残念ながらVSはこれらをサポートしていないようです。誰かが私が必要なものを達成するための別の方法を知っていますか?
Visual Studioには、いくつかのプロジェクトを含むソリューションがあります。どのプロジェクトが関係していて、それらが最新であるかどうかに関係なく、すべてのビルドの最初にコマンドを実行したいと思います。
基本的に、ソリューション全体のビルド前イベントに似たものが必要ですが、残念ながらVSはこれらをサポートしていないようです。誰かが私が必要なものを達成するための別の方法を知っていますか?
異常な要件。しかし、それは可能です。ソリューションに新しいプロジェクトを追加し、VisualC++>一般>Makefileプロジェクトテンプレートを使用します。NMake> Build Command Line設定を、実行するコマンドに設定します。[プロジェクト]>[プロジェクトの依存関係]を使用して、他のすべてのプロジェクトがそれに依存するようにします。
以下の私の亜種の簡単な概要
注:これは既存のすべての不完全なリストです(他の回答なども参照してください)。実際の状態での元のトリックのみをサポートします...
ノート:
targets mode
msbuild.exeでのみ使用可能なを呼び出す簡単な方法after.<name>.sln.targets
(これには追加の手順は必要なく、単にアクションが必要です)。ただし、元のエンジン(vsCommandEventを含む)のみが、たとえば(7zipアーカイバ、nuget.exeなしのnugetパッケージのパッキング、リモートサーバーなど)をサポートする追加のスクリプトを許可する場合があります。ただし、私たちの質問/問題にとっては重要ではなく、上記の場合は、利用可能なオプションを使用してソリューションレベルをサポートできます+
。この亜種は、VSの単純なユーザー向けではありません。ただし、完全なソリューションなどには役立ちます。
たとえば、次のように実装する必要があります。
例えば:
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);
どこ:
sbm
GCから保護するためのクラスの一部である必要があります。これで、すべてのプロジェクトを一度に処理できます-ソリューションレベル。
わかりました、あなたはこのようなものが好きです-MSBuild:ソリューションビルドを拡張しますが、このバリアントはVSIDEからではなくmsbuild.exeからのビルドプロセスで動作する可能性があります...
ただし、VSは、ビルド操作の開始時に、プロジェクトファイル(* .csproj、*。vcxproj、..)でターゲット(Build、Rebuild、Clean、..)も使用します。したがって、これを試すこともできますが、覚えておいてください。
...
<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" />
したがって、VS IDEの一般的なターゲットを操作する場合は、制限のあるプロジェクトファイルのみを使用できます(VSの変更/拡張なし、つまり)。
したがって、一般的なソリューションが必要な場合(つまり、プロジェクトなどについて知らない場合があります。これは、たとえば、一部のボックスソリューションなどの場合です)。
<Import Project="..\<SolutionFile>.targets" />
そして、例えば、はい、それは「プロジェクトの地図」である可能性があります:
...
<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>
最初の初期化で新しいプロジェクトのセクションを管理する必要があります。これは本当に不便ですが、バリエーションもあります...
今日では、プロジェクトとライブラリのメンテナンス、プロセスの構築、およびVisualStudioとMSBuildツールからの実行時のプロセスのためのさまざまな高度なアクションを備えたEvents-Catcherとして、多くのイベントを処理するための最も完全なソリューションです。
ソリューション内のすべてのサブプロジェクトに対して、ソリューションイベントとして一度に、またはそれぞれに個別に、さまざまなアクションタイプ。
https://visualstudiogallery.msdn.microsoft.com/0d1dbfd7-ed8a-40af-ae39-281bfeca2334/
上記のVariant1を使用する場合、またはShell.Interop、EnvDTE、IVsUpdateSolutionEvents2、MSBuild Engineなどの操作方法を確認する必要がある場合は、次を参照してください。
この亜種は、VSの単純なユーザー向けでもありません。ただし、バリアント1については、ボックスソリューションなどに役立ちます。
同じではありませんが、はい、上記のバリアント1のようにEnvDTE.CommandEventsでも可能です。
現在のタイプのビルドアクションで優先的に作業するためのこのソリューションについては、すでに知っている必要があります(上記を参照)...では、これを現在の問題の主要なソリューションとして使用しないのはなぜですか?
_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/
さらに、オプションで、必要に応じてこのコマンドを非表示にすることができます。以下のバリアントでは、この方法の完全なソリューションが表示されます。
https://visualstudiogallery.msdn.microsoft.com/ad9f19b2-04c0-46fe-9637-9a52ce4ca661/
また、ほとんどのイベントの高度なハンドラーも提供しますが、最初のハンドラーとは異なり、すべてのコマンドと出力データをマネージャーとして使用する高度な作業のためにMSVisualStudioに特化しています。プロジェクトやソリューションだけでなく、VisualStudioIDE全体にも使用できます。
一般に、これはVariant 4の一般的な解決策であり、上記のすべてのコマンドをオーバーライドするだけで、この問題を解決できます。
また、vsSolutionBuildEventのような同じイベントアクションモデルの場合、ほとんどの場合に役立ちます。
これらすべてのバリアントにはオープンな実装があります。ここを見て笑顔:
この記事をご覧ください:MSBuild:ソリューションビルドの拡張。
まさにあなたが必要としているもののようです。
これを行うには、空のプロジェクトを追加し、このプロジェクトのビルドイベントを設定します。次に、この空のプロジェクトに各プロジェクトの依存関係を与えて、毎回ビルドされるようにする必要があります。
別の古い投稿ですが、@ regソリューションに触発されて、ソリューションビルドの経過時間をログに記録する単純なビルドタイマーを実行したいと思いました。VisualStudioIDEの起動時にパッケージマネージャーコンソールからロードするPowerShellモジュールを使用してビルドイベントを機能させました。
したがって、次のような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
パッケージマネージャーホストが初期化するときにモジュールをインポートします。
NuGet_profile.ps1
) 。メモ帳でファイルを開き、次の行を追加します
Import-Module -Name <Path to your ps module>\BuildEvents -Force
RegisterBuildEvents
しばらく経ちましたが、それ以降、.Netインフラストラクチャの一部が変更され、新しいオプションが提供されています。この問題の王様を解決するための私の選択は、nugetパッケージです。ビルドステップをパッケージに入れ、それをすべてのプロジェクトに含めました。便利なことに、Visual Studioパッケージマネージャーはソリューションレベルでパッケージの概要を提供するため、このルールを確認するのは非常に簡単です。
MSBUILD 15でビルドされているコードの場合、最も簡単な方法は、プロジェクトが存在するパス(必ずしもソリューションフォルダーではない)のルートにDirectory.Build.targetsファイルを配置し、それをカスタマイズすることです。これは、Visual Studio内から、またはコマンドプロンプトを使用してビルドする場合でも実行されます。
https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?view=vs-2019