Создайте собственный сценарий powershell для nuget, который добавляет пользовательскую цель на шаг csproj BeforeBuild.

Я хочу создать пакет nuget, который добавляет шаг BeforeBuild в мой csproj, используя созданную мной пользовательскую задачу MSBuild. В идеале я хочу:

  1. Добавьте новую цель в файл csproj (MyCustomBeforeBuildTarget)
  2. Добавьте цель BeforeBuild, если ее еще нет
  3. Отредактируйте атрибут BeforeBuild DependsOnTargets, чтобы включить мою пользовательскую цель

Итак, после установки мой csproj должен иметь следующее:

<Target Name="MyCustomBeforeBuildTarget" Condition="SomeCondition">
     <MyCustomTask />
</Target>
<Target Name="BeforeBuild" DependsOnTargets="MyCustomBeforeBuildTarget">

</Target>

Кроме того, было бы неплохо, если бы при удалении моего пакета пользовательская цель тоже исчезала, хотя я добавил условие, которое должно заставить ее игнорировать цель, если моя пользовательская библиотека DLL задачи отсутствует.

Какой самый простой сценарий установки Powershell nuget, который я могу написать, добавит мою пользовательскую цель? У меня есть ощущение, что сценарии PowerShell здесь могут стать частью решения, но мне не хватает Опыт PowerShell, чтобы знать, как на самом деле использовать их для редактирования файла csproj.


person Mark Heath    schedule 13.06.2011    source источник


Ответы (2)


NuGetPowerTools — это пакет, который добавляет некоторые функции PowerShell, упрощающие работу с настройкой проекта. вы добавляете пакет. Чтобы использовать доступные функции, вам нужно только сделать ваш пакет зависимым от NuGetPowerTools, используя тег зависимостей в вашем файле nuspec пакетов следующим образом:

<dependencies>
  <dependency id="NuGetPowerTools" version="0.26" />
</dependencies>

Это позволит получить ссылку на представление проекта сборки вашего проекта.

Затем вам нужно поместить файл install.ps1 в папку tools вашего пакета NuGet, этот файл PowerShell будет запускаться при установке пакета и никогда больше после установки.

Файл должен выглядеть примерно так:

#First some common params, delivered by the nuget package installer
param($installPath, $toolsPath, $package, $project)

# Grab a reference to the buildproject using a function from NuGetPowerTools
$buildProject = Get-MSBuildProject

# Add a target to your build project
$target = $buildProject.Xml.AddTarget("PublishWebsite")

# Make this target run before build
# You don't need to call your target from the beforebuild target,
# just state it using the BeforeTargets attribute
$target.BeforeTargets = "BeforeBuild"

# Add your task to the newly created target
$target.AddTask("MyCustomTask")

# Save the buildproject
$buildProject.Save()

# Save the project from the params
$project.Save()

Это должно быть так.

С Уважением

Джеспер Хауге

person Hauge    schedule 08.09.2011
comment
Я использовал этот подход, и я столкнулся со следующей проблемой. Если в вашем решении несколько проектов и вы используете пользовательский интерфейс (щелчок правой кнопкой мыши по проекту -> Управление пакетами NuGet), то Get-MSBuildProject возвращает не проект, на который вы нажали, а проект, выбранный в консоли диспетчера пакетов. Кажется, что использование имени проекта решает эту проблему: $buildProject = Get-MSBuildProject $project.ProjectName - person admax; 11.02.2013
comment
Есть ли где-нибудь документация по NuGetPowerTools? Не похоже. - person mhenry1384; 26.03.2016

Следующий код взят из пакета CodeAssassin.WixWebProjectReferences. Он добавляет и удаляет следующий тег импорта в файл проекта при установке и удалении. Пакет не требует никаких зависимостей.

<Import Project="..\packages\CodeAssassin.WixWebProjectReferences.1.0\tools\CodeAssassin.WixWebProjectReferences.targets" />

Загрузите пакет и откройте его с помощью NuGetPackageExplorer, чтобы увидеть, как это делается.

Ниже приведен код из install.ps1 и uninstall.ps1 (они выполняются только в том случае, если папка содержимого NuGet-пакета не пуста).

(Я не смог найти какую-либо подсветку powershell, поэтому вместо этого я использовал php, и это не идеально.)

install.ps1

param (
    $InstallPath,
    $ToolsPath,
    $Package,
    $Project
)

$TargetsFile = 'CodeAssassin.WixWebProjectReferences.targets'
$TargetsPath = $ToolsPath | Join-Path -ChildPath $TargetsFile

Add-Type -AssemblyName 'Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'

$MSBProject = [Microsoft.Build.Evaluation.ProjectCollection]::GlobalProjectCollection.GetLoadedProjects($Project.FullName) |
    Select-Object -First 1

$ProjectUri = New-Object -TypeName Uri -ArgumentList "file://$($Project.FullName)"
$TargetUri = New-Object -TypeName Uri -ArgumentList "file://$TargetsPath"

$RelativePath = $ProjectUri.MakeRelativeUri($TargetUri) -replace '/','\'

$ExistingImports = $MSBProject.Xml.Imports |
    Where-Object { $_.Project -like "*\$TargetsFile" }
if ($ExistingImports) {
    $ExistingImports | 
        ForEach-Object {
            $MSBProject.Xml.RemoveChild($_) | Out-Null
        }
}
$MSBProject.Xml.AddImport($RelativePath) | Out-Null
$Project.Save()

удалить.ps1

param (
    $InstallPath,
    $ToolsPath,
    $Package,
    $Project
)

$TargetsFile = 'CodeAssassin.WixWebProjectReferences.targets'

Add-Type -AssemblyName 'Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'

$MSBProject = [Microsoft.Build.Evaluation.ProjectCollection]::GlobalProjectCollection.GetLoadedProjects($Project.FullName) |
    Select-Object -First 1

$ExistingImports = $MSBProject.Xml.Imports |
    Where-Object { $_.Project -like "*\$TargetsFile" }
if ($ExistingImports) {
    $ExistingImports | 
        ForEach-Object {
            $MSBProject.Xml.RemoveChild($_) | Out-Null
        }
    $Project.Save()
}

Образец target-файла, который копирует некоторые файлы в выходной путь

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
    <ItemGroup>
        <Files Include="..\packages\Insert_Path_To_Your_Package_Folder_Here\bin\*" />
    </ItemGroup>
    <Target Name="Insert_Name_of_Your_Target_Here" AfterTargets="AfterBuild">
        <Copy SourceFiles="@(Files)" DestinationFolder="$(TargetDir)\bin\" SkipUnchangedFiles="true" />
    </Target>
</Project>
person haiiaaa    schedule 27.08.2012
comment
Отлично. Я хотел, чтобы мой файл target был в проекте, поэтому я сделал это, чтобы получить $TargetsPath при установке: $fileInfo = new-object -typename System.IO.FileInfo -ArgumentList $Project.FullName; $projectDirectory = $fileInfo.DirectoryName; $TargetsFile = 'solutionBinFilesForAdmincenter.targets; $TargetsPath = $projectDirectory | Путь присоединения - ChildPath $TargetsFile - person mhenry1384; 27.03.2016