使用 .targets 文件使用 NuGet 设置文件属性 [英] Setting file properties with NuGet using .targets file

查看:23
本文介绍了使用 .targets 文件使用 NuGet 设置文件属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个要作为 NuGet 包安装的项目,并且我想设置 SpecFlow 功能文件的属性(因为它是最新的 SpecFlow,不应为这些功能生成代码隐藏文件.)

为了达到选择文件、打开属性窗格并设置几个值的效果,我将项目结构设置为:

<代码>MyProject建造我的项目.targetsFramework <包含我想要影响的文件的文件夹>FrameworkTests.feature <我想要影响的文件>框架FrameworkTests.feature <我要影响的文件的原始位置>

我的 .nuspec 是这样的:

<?xml version="1.0"?><包><元数据 minClientVersion="2.5"><id>$id$</id><版本>$版本$</版本>...</元数据><文件><file src="buildMyProject.targets" target="buildMyProject.targets"/><file src="buildFrameworkTestsFrameworkTests.feature" target="buildFrameworkFrameworkTests.feature"/></文件></包>

我的 .targets 文件是这样的:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"><项目组><无包含="$(MSBuildThisFileDirectory)FrameworkTestsFrameworkTests.feature"><Link>FrameworkTests.feature</Link><CopyToOutputDirectory>如果更新则复制</CopyToOutputDirectory><CustomToolNamespace></CustomToolNamespace></无></项目组></项目>

安装包时,我没有看到 FrameworkTests.feature 文件被复制到项目中.我需要改变什么?

解决方案

安装包时,我没有看到 FrameworkTests.feature 文件被复制到项目中.我需要改变什么?

这是 nuget 文件夹约定的默认行为.如果您在 content 文件夹中设置文件,nuget 会将这些内容复制到项目根目录,然后您将在解决方案资源管理器中看到它们.如果您在 build 文件夹中设置文件,nuget 会自动将它们插入到项目文件或 project.lock.json 中,如项目文件中的以下脚本:

<Import Project="..packagesMyProject.1.0.0uildMyProject.targets" Condition="Exists('..packagesMyProject.1.0.0uildMyProject.目标')"/>

因此,这就是为什么您无法在解决方案资源管理器中看到文件 FrameworkTests.feature 的原因,除非您将文件夹更改为 content.

可以参考文档

此外,如果将文件夹更改为内容,.targets 将不起作用.因为当你把文件夹改成内容的时候,在.targets文件中,需要把路径从:

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

收件人:

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

但 MSBuild 无法解析路径 ..content.要解决此问题,我们需要将 .targets 文件更改为:

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

或者,您可以使用 Install.ps1 文件更改文件的属性,将其设置到 nuget 包中.

请参阅

希望这会有所帮助.

I am building a project to be installed as a NuGet package and I want to set the properties of a SpecFlow feature file (because it is latest SpecFlow and should not produce code-behind files for the features.)

To achieve the effect of selecting a file, opening it's Properties pane and setting a couple of values, I have set my project structure like this:

MyProject
  uild
    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>

My .nuspec like this:

<?xml version="1.0"?>
<package >
  <metadata minClientVersion="2.5">
    <id>$id$</id>
    <version>$version$</version>
    ...
  </metadata>
  <files>
    <file src="buildMyProject.targets" target="buildMyProject.targets" />
    <file src="buildFrameworkTestsFrameworkTests.feature" target="buildFrameworkFrameworkTests.feature" />
  </files>
</package>

My .targets file like this:

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

I am not seeing the FrameworkTests.feature file get copied to the project when the package is installed. What do I need to change?

解决方案

I am not seeing the FrameworkTests.feature file get copied to the project when the package is installed. What do I need to change?

This is the default behavior of the nuget folder conventions. If you set the file in the content folder, nuget will copy those contents to the project root, then you will see them in the solution explorer. If you set files in the build folder, nuget will automatically inserted them into the project file or project.lock.json, like following script in the project file:

<Import Project="..packagesMyProject.1.0.0uildMyProject.targets" Condition="Exists('..packagesMyProject.1.0.0uildMyProject.targets')" />

So, this is the reason why you could not see the file FrameworkTests.feature in the solution explorer unless you change the folder to content.

You can refer to the document Creating the .nuspec file for more details:

Besides, if you change the folder to content, the .targets would not work. Because when you change the folder to content, in the .targetsfile, you need to change the path from:

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

To:

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

But MSBuild could not parse the path ..content. To resolve this issue, we need to change the .targets file to:

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

Alternatively, you can change property of files with Install.ps1 file, set it into the nuget package.

See this thread for more details.

Update:

I have also applied the changes you've described, but still cannot get the CopyToOutputDirectory file property to be updated.

Found it. There are two points you need update and one point should to know.

First point:

I found following script in your .nuspec:

  <files>
    <file src="buildMyProject.targets" target="buildMyProject.targets" />
    <file src="buildFrameworkTestsFrameworkTests.feature" target="buildFrameworkFrameworkTests.feature" />
  </files>

Note: You set your target folder for buildFramework but in your .targets file, you including it with FrameworkTests;

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

So, when change it to content folder, your .nuspec file should be:

  <files>
    <file src="buildMyProject.targets" target="buildMyProject.targets" />
    <file src="contentFrameworkTestsFrameworkTests.feature" target="contentFrameworkTestsFrameworkTests.feature" />
  </files>

And the .targets file should be:

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

Second point need update:

The value of CopyToOutputDirectory in the .targets file should be PreserveNewest Not Copy if newer.

The point you need to know:

When you use this method to change the property of the FrameworkTests.feature, the property of this file would not changed in the solution explorer, however, MSBuild will apply this change when you build the project. That because <Import Project="....MyProject.targets" Condition="Exists('...')" /> will be parsed when you compile the project.

So, you can check the output for CopyToOutputDirectory file property after build the project(After build your project, the file FrameworkTests.feature would be copied to the output folder.)

Update2:

A lot of comments circulating that PowerShell scripts can't be run on build servers because the install command doesn't run them; Only VisualStudio will

Not sure of all the reasons why PowerShell scripts can't be run on build servers, but the vast majority are because PowerShell's default security level.

Try typing this in the PowerShell:

set-executionpolicy remotesigned

In the Visual Studio 2015, you need to install the extension PowerShell Tools for Visual Studio 2015 and the Windows Management Framework 4.0. After install them, the install.ps1 would works fine. Following is my .nuspec file and install.ps1 script.

.nuspec file:

  <files>
    <file src="contentFrameworkTestsFrameworkTests.feature" target="contentFrameworkTestsFrameworkTests.feature" />
    <file src="scriptsInstall.ps1" target="toolsInstall.ps1" />
  </files>

Note: Do not forget remove the MyProject.targets in the .nuspec file.

install.ps`1 script:

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

Then, after install the nuget package, the property of the file FrameworkTests.feature would be changed to copy if newer:

Hope this helps.

这篇关于使用 .targets 文件使用 NuGet 设置文件属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆