web-dev-qa-db-ja.com

.targetsファイルを使用してNuGetでファイルプロパティを設定する

NuGetパッケージとしてインストールするプロジェクトを構築していて、SpecFlow機能ファイルのプロパティを設定したい(これは最新のSpecFlowであり、機能のコードビハインドファイルを生成するべきではないため)。

ファイルを選択し、そのプロパティペインを開き、いくつかの値を設定する効果を実現するために、プロジェクト構造を次のように設定しました。

\MyProject
  \build
    MyProject.targets
    \Framework <the folder containing the file I want to affect>
      FrameworkTests.feature <the file I want to affect>
  \Framework
    FrameworkTests.feature <the original location of the file I want to affect>

このような私の.nuspec:

<?xml version="1.0"?>
<package >
  <metadata minClientVersion="2.5">
    <id>$id$</id>
    <version>$version$</version>
    ...
  </metadata>
  <files>
    <file src="build\MyProject.targets" target="build\MyProject.targets" />
    <file src="build\FrameworkTests\FrameworkTests.feature" target="build\Framework\FrameworkTests.feature" />
  </files>
</package>

このような私の.targetsファイル:

<Project xmlns="http://schemas.Microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <None Include="$(MSBuildThisFileDirectory)FrameworkTests\FrameworkTests.feature">
      <Link>FrameworkTests.feature</Link>
      <CopyToOutputDirectory>Copy if newer</CopyToOutputDirectory>
      <CustomToolNamespace></CustomToolNamespace>
    </None>
  </ItemGroup>
</Project>

パッケージのインストール時に、FrameworkTests.featureファイルがプロジェクトにコピーされるのが表示されません。何を変更する必要がありますか?

4
Matt W

パッケージのインストール時に、FrameworkTests.featureファイルがプロジェクトにコピーされるのが表示されません。何を変更する必要がありますか?

これは、nugetフォルダー規則のデフォルトの動作です。ファイルをcontentフォルダーに設定すると、nugetはそれらのコンテンツをプロジェクトルートにコピーし、ソリューションエクスプローラーに表示します。 buildフォルダーにファイルを設定すると、nugetは、プロジェクトファイル内の次のスクリプトのように、ファイルをプロジェクトファイルまたはproject.lock.jsonに自動的に挿入します。

<Import Project="..\packages\MyProject.1.0.0\build\MyProject.targets" Condition="Exists('..\packages\MyProject.1.0.0\build\MyProject.targets')" />

したがって、これが、フォルダーをcontentに変更しない限り、ソリューションエクスプローラーにファイルFrameworkTests.featureが表示されない理由です。

詳細については、ドキュメント 。nuspecファイルの作成 を参照してください。

NuGet folder conventions

のほかに、フォルダをコンテンツに変更すると、.targetsは機能しません。フォルダをコンテンツに変更する場合、.targetsfileで、パスを次の場所から変更する必要があるためです。

<None Include="$(MSBuildThisFileDirectory)FrameworkTests\FrameworkTests.feature">

に:

<None Include="$(MSBuildThisFileDirectory)..\content\FrameworkTests\FrameworkTests.feature">

しかし、MSBuildはパス..\contentを解析できませんでした。この問題を解決するには、.targetsファイルを次のように変更する必要があります。

<None Include="$(ProjectDir)FrameworkTests.feature">

または、Install.ps1ファイルを使用してファイルのプロパティを変更し、nugetパッケージに設定することもできます。

詳細については、 このスレッド を参照してください。

更新:

説明した変更も適用しましたが、CopyToOutputDirectoryファイルプロパティを更新できません。

それを見つけた。更新が必要なポイントが2つあり、知っておくべきポイントが1つあります。

最初のポイント:

.nuspecに次のスクリプトが見つかりました:

  <files>
    <file src="build\MyProject.targets" target="build\MyProject.targets" />
    <file src="build\FrameworkTests\FrameworkTests.feature" target="build\Framework\FrameworkTests.feature" />
  </files>

注:ターゲットフォルダーをbuild\Frameworkに設定しましたが、.targetsファイルでは、FrameworkTestsに含めています。

<None Include="$(MSBuildThisFileDirectory)FrameworkTests\FrameworkTests.feature">

したがって、コンテンツフォルダに変更する場合、.nuspecファイルは次のようになります。

  <files>
    <file src="build\MyProject.targets" target="build\MyProject.targets" />
    <file src="content\FrameworkTests\FrameworkTests.feature" target="content\FrameworkTests\FrameworkTests.feature" />
  </files>

また、.targetsファイルは次のようになります。

<Project xmlns="http://schemas.Microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <None Include="$(ProjectDir)FrameworkTests\FrameworkTests.feature">
      <Link>FrameworkTests.feature</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CustomToolNamespace></CustomToolNamespace>
    </None>
  </ItemGroup>
</Project>

2番目のポイントは更新が必要です:

.targetsファイルのCopyToOutputDirectoryの値は、PreserveNewest新しい場合はコピーしないでください。

知っておくべきポイント

このメソッドを使用してFrameworkTests.featureのプロパティを変更すると、このファイルのプロパティはソリューションエクスプローラーで変更されませんが、MSBuildはプロジェクトのビルド時にこの変更を適用します。これは、プロジェクトをコンパイルするときに<Import Project="....\MyProject.targets" Condition="Exists('...')" />が解析されるためです。

したがって、プロジェクトのビルド後にCopyToOutputDirectoryファイルプロパティの出力を確認できます(プロジェクトのビルド後、ファイルFrameworkTests.featureは出力フォルダーにコピーされます)。

Update2:

インストールコマンドがスクリプトを実行しないため、PowerShellスクリプトをビルドサーバーで実行できないという多くのコメントが出回っています。 VisualStudioのみが

PowerShellスクリプトをビルドサーバーで実行できない理由はすべてわかりませんが、大部分はPowerShellのデフォルトのセキュリティレベルが原因です。

PowerShellでこれを入力してみてください。

set-executionpolicy remotesigned

Visual Studio 2015では、拡張機能 PowerShell Tools for Visual Studio 2015 および Windows Management Framework 4. をインストールする必要があります。それらをインストールした後、install.ps1は正常に動作します。以下は私の.nuspecファイルとinstall.ps1スクリプトです。

。nuspecファイル:

  <files>
    <file src="content\FrameworkTests\FrameworkTests.feature" target="content\FrameworkTests\FrameworkTests.feature" />
    <file src="scripts\Install.ps1" target="tools\Install.ps1" />
  </files>

注:MyProject.targetsファイルの.nuspecを削除することを忘れないでください。

install.ps`1スクリプト:

param($installPath, $toolsPath, $package, $project)

function MarkDirectoryAsCopyToOutputRecursive($item)
{
    $item.ProjectItems | ForEach-Object { MarkFileASCopyToOutputDirectory($_) }
}

function MarkFileASCopyToOutputDirectory($item)
{
    Try
    {
        Write-Host Try set $item.Name
        $item.Properties.Item("CopyToOutputDirectory").Value = 2
    }
    Catch
    {
        Write-Host RecurseOn $item.Name
        MarkDirectoryAsCopyToOutputRecursive($item)
    }
}

#Now mark everything in the a directory as "Copy to newer"
MarkDirectoryAsCopyToOutputRecursive($project.ProjectItems.Item("FrameworkTests"))

次に、nugetパッケージをインストールした後、FrameworkTests.featureファイルのプロパティがcopy if newerに変更されます。

enter image description here

お役に立てれば。

8
Leo Liu-MSFT