Настройка свойств файла с помощью NuGet с использованием файла .targets

Я создаю проект для установки в виде пакета 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 копировался в проект при установке пакета. Что мне нужно изменить?


person Matt W    schedule 12.04.2018    source источник
comment
I am not seeing the FrameworkTests.feature file get copied to the project -Ты имеешь в виду файл FrameworkTests.feature не добавленный в твой проект, ты не мог его увидеть в обозревателе решений?   -  person Leo Liu-MSFT    schedule 12.04.2018
comment
да. Я вижу, что это добавляется в обозреватель решений, только если я использую target="content\Framework\FrameworkTests.feature"   -  person Matt W    schedule 12.04.2018


Ответы (1)


Я не вижу, чтобы файл 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')" />

Итак, по этой причине вы не могли видеть файл FrameworkTests.feature в обозревателе решений, если не изменили папку на content.

Вы можете обратиться к документу Создание файла .nuspec для получения дополнительной информации:

«Соглашения

Кроме того, если вы измените папку на содержимое, .targets не будет работать. Потому что когда вы меняете папку на содержимое, в .targetsфайле вам нужно изменить путь с:

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

To:

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

Но MSBuild не удалось разобрать путь ..\content. Чтобы решить эту проблему, нам нужно изменить файл .targets на:

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

В качестве альтернативы вы можете изменить свойство файлов с помощью файла Install.ps1, установить его в пакет nuget.

См. эту тему для подробнее.

Обновление:

Я также применил описанные вами изменения, но по-прежнему не могу обновить свойство файла CopyToOutputDirectory.

Нашел. Есть две точки, которые вам нужно обновить, и одну точку следует знать.

Первый пункт:

Я нашел следующий скрипт в вашем .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>

Второй пункт требует обновления:

Значение CopyToOutputDirectory в файле .targets должно быть PreserveNewest Не копировать, если оно новее.

Что вам нужно знать:

Когда вы используете этот метод для изменения свойства FrameworkTests.feature, свойство этого файла не изменится в обозревателе решений, однако MSBuild применит это изменение при сборке проекта. Это потому, что <Import Project="....\MyProject.targets" Condition="Exists('...')" /> будет проанализировано при компиляции проекта.

Таким образом, вы можете проверить вывод для свойства файла CopyToOutputDirectory после сборки проекта (после сборки вашего проекта файл FrameworkTests.feature будет скопирован в выходную папку.)

Обновление 2:

Много комментариев о том, что сценарии PowerShell нельзя запускать на серверах сборки, потому что команда установки их не запускает; Только VisualStudio будет

Не уверен во всех причинах, по которым сценарии PowerShell нельзя запускать на серверах сборки, но подавляющее большинство из них связано с уровнем безопасности PowerShell по умолчанию.

Попробуйте ввести это в PowerShell:

set-executionpolicy remotesigned

В Visual Studio 2015 необходимо установить расширение Инструменты PowerShell для Visual Studio 2015 и Windows Management Framework 4.0. После их установки 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:

введите описание изображения здесь

Надеюсь это поможет.

person Leo Liu-MSFT    schedule 12.04.2018
comment
Я уже пытался добавить папку content и поместить в нее файлы, но они не были скопированы в целевой проект при установке пакета nuget. Я упаковываю, указав имя .csproj - подразумевает ли это разницу? Я также применил описанные вами изменения, но все еще не могу обновить свойство файла CopyToOutputDirectory. - person Matt W; 12.04.2018
comment
@MattW, должно быть что-то, что я не объяснил четко, я обновлю свой ответ позже и дам вам знать об этом. - person Leo Liu-MSFT; 12.04.2018
comment
@MattW, после создания образца с вашими файлами .nuspec и .targets я нашел причину, по которой он не работает для вас, есть два момента, которые вам нужно обновить, и один момент, который следует знать. Подробности см. в моем ответе на обновление. И я протестировал его, он отлично работает на моей стороне, если он все еще не работает для вас, пожалуйста, дайте мне знать. - person Leo Liu-MSFT; 12.04.2018
comment
Спасибо. На первый взгляд я вижу, что PreserveNewest — это изменение, которое я уже внес. Взглянем дальше... - person Matt W; 12.04.2018
comment
Итак, я применил все, что вы сказали. Спасибо вам за помощь. Остается одна проблема... Вы заметите, что файлы, к которым я пытаюсь применить изменения свойств, являются .feature файлами - они используются с SpecFlow/xUnit, и при изменении этих свойств в Visual Studio подключаемый модуль SpecFlow удаляет код- за файлами .cs, которые поддерживают файлы .feature. Поскольку NuGet в настоящее время используется, этого не происходит, и когда я создаю проект (после установки пакета NuGet) и пытаюсь запустить тесты SpecFlow/xUnit, сборка жалуется, потому что считает, что автоматически сгенерированные файлы .cs существуют. - person Matt W; 12.04.2018
comment
Еще одна ошибка, которую я вижу, заключается в том, что файлы .feature копируются в файл bin\Debug\FrameworkTests` folder, which means the Test Explorer shows 3 copies of each .feature` целевого проекта, а не в папку проекта. Как я могу предотвратить создание элемента bin\Debug при установке пакета? - person Matt W; 12.04.2018
comment
@MattW, поскольку вы ограничены SpecFlow/xUnit, вы можете использовать другой способ, который я упомянул в ответе. Используя файл Install.ps1, в этом случае, когда вы завершите установку пакета nuget, nuget изменит свойство. stackoverflow.com/questions/8474253/ - person Leo Liu-MSFT; 12.04.2018
comment
Много комментариев о том, что сценарии PowerShell нельзя запускать на серверах сборки, потому что команда установки их не запускает; Только VisualStudio будет. :( - person Matt W; 12.04.2018
comment
@MattW, не уверен во всех причинах, по которым сценарии PowerShell нельзя запускать на серверах сборки, но подавляющее большинство из них связано с уровнем безопасности PowerShell по умолчанию. Вы можете проверить мой ответ update2 для получения подробной информации, он отлично работает, когда я устанавливаю этот пакет nuget в VS2015. - person Leo Liu-MSFT; 12.04.2018
comment
Спасибо! Ты великолепен! Нет слов! Исключительно! Большое спасибо! - person Matt W; 13.04.2018
comment
Эй, я просто хочу сказать, что это мне очень помогло. Спасибо! - person bruestle2; 20.04.2021