79

Visual Studioには、いくつかのプロジェクトを含むソリューションがあります。どのプロジェクトが関係していて、それらが最新であるかどうかに関係なく、すべてのビルドの最初にコマンドを実行したいと思います。

基本的に、ソリューション全体のビルド前イベントに似たものが必要ですが、残念ながらVSはこれらをサポートしていないようです。誰かが私が必要なものを達成するための別の方法を知っていますか?

4

7 に答える 7

45

異常な要件。しかし、それは可能です。ソリューションに新しいプロジェクトを追加し、VisualC++>一般>Makefileプロジェクトテンプレートを使用します。NMake> Build Command Line設定を、実行するコマンドに設定します。[プロジェクト]>[プロジェクトの依存関係]を使用して、他のすべてのプロジェクトがそれに依存するようにします。

于 2010-02-19T10:31:05.237 に答える
44

以下の私の亜種の簡単な概要

注:これは既存のすべての不完全なリストです(他の回答なども参照してください)。実際の状態での元のトリックのみをサポートします...

まとめ

ノート:

  • 1-追加の拡張機能は必要ありません。ただし、プロジェクトレベルでのみ機能する可能性があるため、ソリューションレベルをエミュレートするために使用します...一般的なソリューションでは困難で不便ですが、バリエーションがあります。下記参照。
  • 2 -vsSolutionBuildEventの元のエンジンは、VSとmsbuild.exeの統合サポートのいくつかの方法を提供します。targets modemsbuild.exeでのみ使用可能なを呼び出す簡単な方法after.<name>.sln.targets(これには追加の手順は必要なく、単にアクションが必要です)。ただし、元のエンジン(vsCommandEventを含む)のみが、たとえば(7zipアーカイバ、nuget.exeなしのnugetパッケージのパッキング、リモートサーバーなど)をサポートする追加のスクリプトを許可する場合があります。ただし、私たちの質問/問題にとっては重要ではなく、上記の場合は、利用可能なオプションを使用してソリューションレベルをサポートできます+

バリアント1:Microsoft.VisualStudio.Shell.Interop

この亜種は、VSの単純なユーザー向けではありません。ただし、完全なソリューションなどには役立ちます。

たとえば、次のように実装する必要があります。

例えば:

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

次に、ハンドラーを「Advise」メソッドで優先リスナーとして登録します。つまり、IVsUpdateSolutionEvents2の場合は、 AdviseUpdateSolutionEventsを使用する必要があります。

BuildEventsEnvDTEを参照)-おそらく役に立たず、遅すぎる可能性があるため、これは重要です-

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);

どこ:

  • フィールドは、sbmGCから保護するためのクラスの一部である必要があります。
  • SVsSolutionBuildManagerサービスを取得するには、ServiceProviderを使用しますが、必要に応じて使用できます。msdnを参照してください

これで、すべてのプロジェクトを一度に処理できます-ソリューションレベル。

バリエーション2:プロジェクトのターゲットとマップ。

わかりました、あなたはこのようなものが好きです-MSBuild:ソリューションビルドを拡張しますが、このバリアントはVSIDEからではなくmsbuild.exeからのビルドプロセスで動作する可能性があります...

ただし、VSは、ビルド操作の開始時に、プロジェクトファイル(* .csproj、*。vcxproj、..)でターゲット(Build、Rebuild、Clean、..)も使用します。したがって、これを試すこともできますが、覚えておいてください。

  • 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もVSIDEで表示できません。

したがって、VS IDEの一般的なターゲットを操作する場合は、制限のあるプロジェクトファイルのみを使用できます(VSの変更/拡張なし、つまり)。

したがって、一般的なソリューションが必要な場合(つまり、プロジェクトなどについて知らない場合があります。これは、たとえば、一部のボックスソリューションなどの場合です)。

  • 共通の.targetsファイルをすべてのプロジェクトに追加します(NuGetイベントなどの任意のツールで自動的に実行できます)。次に例を示します。<Import Project="..\<SolutionFile>.targets" />
  • 次に、次の制限を使用する必要があります。
    • 「のみ-すべてのプロジェクトの前に」
    • 「のみ-すべてのプロジェクトの後」

そして、例えば、はい、それは「プロジェクトの地図」である可能性があります:

  • プロジェクトのマップ」は、Visual Studio IDE(つまり、VS IDEからのプライマリ)からのビルド操作のソリューション全体のPRE/POST「イベント」を示しています。
...
<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

今日では、プロジェクトとライブラリのメンテナンス、プロセスの構築、およびVisualStudioとMSBuildツールからの実行時のプロセスのためのさまざまな高度なアクションを備えたEvents-Catcherとして、多くのイベントを処理するための最も完全なソリューションです。

ソリューション内のすべてのサブプロジェクトに対して、ソリューションイベントとして一度に、またはそれぞれに個別に、さまざまなアクションタイプ。

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

プラグイン-vsSolutionBuildEvent

内部でどのように機能するか

上記のVariant1を使用する場合、またはShell.Interop、EnvDTE、IVsUpdateSolutionEvents2、MSBuild Engineなどの操作方法を確認する必要がある場合は、次を参照してください

図式

バリアント4。EnvDTE.CommandEvents

この亜種は、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/

さらに、オプションで、必要に応じてこのコマンドを非表示にすることができます。以下のバリアントでは、この方法の完全なソリューションが表示されます。

バリアント5。プラグインvsCommandEvent

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

また、ほとんどのイベントの高度なハンドラーも提供しますが、最初のハンドラーとは異なり、すべてのコマンドと出力データをマネージャーとして使用する高度な作業のためにMSVisualStudioに特化しています。プロジェクトやソリューションだけでなく、VisualStudioIDE全体にも使用できます。

一般に、これはVariant 4の一般的な解決策であり、上記のすべてのコマンドをオーバーライドするだけで、この問題を解決できます。

また、vsSolutionBuildEventのような同じイベントアクションモデルの場合、ほとんどの場合に役立ちます。

図式

「バリアントを手伝って」

これらすべてのバリアントにはオープンな実装があります。ここを見て笑顔

于 2013-08-19T09:57:22.247 に答える
17

この記事をご覧ください:MSBuild:ソリューションビルドの拡張。

まさにあなたが必要としているもののようです。

于 2011-04-19T17:49:38.700 に答える
9

これを行うには、空のプロジェクトを追加し、このプロジェクトのビルドイベントを設定します。次に、この空のプロジェクトに各プロジェクトの依存関係を与えて、毎回ビルドされるようにする必要があります。

于 2010-02-19T10:24:35.190 に答える
1

別の古い投稿ですが、@ 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

パッケージマネージャーホストが初期化するときにモジュールをインポートします。

  1. パッケージマネージャーコンソールで$profileと入力して、PowerShellプロファイルの場所を取得します
  2. ディスク上のそのディレクトリを参照します。ファイルがない場合は、上記のコマンドで返された名前でファイルを作成します(例 NuGet_profile.ps1) 。
  3. メモ帳でファイルを開き、次の行を追加します

    Import-Module -Name <Path to your ps module>\BuildEvents -Force
    RegisterBuildEvents
    
于 2018-05-23T14:16:23.887 に答える
0

しばらく経ちましたが、それ以降、.Netインフラストラクチャの一部が変更され、新しいオプションが提供されています。この問題の王様を解決するための私の選択は、nugetパッケージです。ビルドステップをパッケージに入れ、それをすべてのプロジェクトに含めました。便利なことに、Visual Studioパッケージマネージャーはソリューションレベルでパッケージの概要を提供するため、このルールを確認するのは非常に簡単です。

于 2018-01-05T18:30:21.637 に答える
0

MSBUILD 15でビルドされているコードの場合、最も簡単な方法は、プロジェクトが存在するパス(必ずしもソリューションフォルダーではない)のルートにDirectory.Build.targetsファイルを配置し、それをカスタマイズすることです。これは、Visual Studio内から、またはコマンドプロンプトを使用してビルドする場合でも実行されます。

https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?view=vs-2019

于 2020-09-05T04:40:29.227 に答える