web-dev-qa-db-ja.com

MSBuild-ソリューションのプロジェクト固有のターゲットが機能しない

Webアプリケーションを含む複数のプロジェクトを含むソリューションがあります。 MSBuildで、Webアプリケーションプロジェクトに対して「WebPublish」ターゲットを実行し、ソリューション内の他のすべてのプロジェクトに対して「デフォルトターゲット」を実行する必要があります。

このMSDN記事 は、コマンドラインを指定して実行できると述べています

msbuild SlnFolders.sln /t:NotInSlnfolder:Rebuild;NewFolder\InSolutionFolder:Clean

しかし、私はそれを機能させることができませんでした-MSBuildは "NotInSlnFolder:Rebuild"ターゲットのような何かが存在しないというエラーを返します。ビルド、リビルド、クリーニングのどのターゲットを指定するかは関係ありません-どの場合でも機能しません。

ソリューションのプロジェクト固有のターゲットを指定するという目標をどのように達成できますか?

MSDNドキュメントは機能しません。それとも私は何かを逃したのですか?

26
Philipp Munin

注:この回避策はMicrosoftによって正式にサポートされていないため、永久に機能する保証はありません。


短い答え

SLNファイルのあるフォルダーに、次の内容のファイルbefore.{YourSolution}.sln.targetsを作成します(中括弧で囲まれたものを必要なものに置き換えます)。

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.Microsoft.com/developer/msbuild/2003">
  <Target Name="{MyCompany_MyProduct_WebApp:WebPublish}">
    <MSBuild
        Condition="'%(ProjectReference.Identity)' == '{$(SolutionDir)MyCompany.MyProduct.WebApp\MyCompany.MyProduct.WebApp.csproj}'"
        Projects="@(ProjectReference)"
        Targets="{WebPublish}"
        BuildInParallel="True"
        ToolsVersion="4.0"
        Properties="BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)"
        SkipNonexistentProjects="%(ProjectReference.SkipNonexistentProjects)" />
  </Target>
</Project>

その後、コマンドラインを実行できます:

msbuild {YourSolution}.sln /t:{MyCompany_MyProduct_WebApp:WebPublish}

長い答え

環境変数MSBUILDEMITSOLUTIONを追加し、その値を1に設定すると、MSBuildはソリューションとプロジェクト用に生成された一時ファイルを削除しません。

これにより、ソリューションフォルダーで生成された{YourSolution}.sln.metaprojおよび{YourSolution}.sln.metaproj.tmpファイルを見つけることができます。これらは、標準のMSBuildプロジェクトファイルです。

MSBuild 3.5の場合、生成されるファイルは{YourSolution}.sln.cacheであり、環境変数に関係なく保持されます。これらのファイルを分析して、プロセスの低レベルの詳細を理解し、利用可能なカスタマイズの機会を確認します。

.Metaprojファイルにプロジェクト固有のターゲットを指定してMSBuildを実行すると、プロジェクト固有のターゲットのリストはハードコードされていますおよび標準ターゲットのみがサポートされています(ビルド、再構築、クリーン、コンパイル、公開。注:公開とWebPublishは同じではありません)。 MSBuild 3.5は、クリーン、リビルド、およびパブリッシュターゲットだけでなく、「」を意味するプロジェクト名のみのターゲットを生成しますビルド "。

また、NotInSlnfolder:Rebuild自動生成されたターゲットの名前であることがわかります。実際には、MSBuildはそれを解析せず、プロジェクトの名前と場所を考慮しません。また、自動生成されたターゲット名がソリューションフォルダー階層でプロジェクト名を指定していることにも注意してください。 SolFolder\SolSubfolder\ProjectName:Publish

MSBuildターゲット名ドットはサポートされていませんプロジェクト名のすべてのドットは下線に置き換えられます。たとえば、MyCompany.MyProduct.Componentsという名前のプロジェクトの場合、コマンドラインで指定する必要があります。

/t:MyCompany_MyProduct_Components:Rebuild

そのため、標準のプロジェクト固有のターゲットビルドでも機能しませんでした。私のプロジェクト名にはdotsが含まれていました。

ファイル{YourSolution}.sln.metaproj.tmpを分析すると、実行時にbefore.{YourSolution}.sln.targetsおよびafter.{YourSolution}.sln.targetsという名前のファイルからターゲットをインポートしようとしていることがわかります(これらのファイルが存在する場合)。これは、このMSBuildの制限/バグの回避策の鍵となります。

40
Philipp Munin

テキストエディターでソリューションファイルを開き、次の行が存在するかどうかを確認できます。存在しない場合は追加できます。

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /><Project> 鬼ごっこ。

これがお役に立てば幸いです。

1
imdadhusen