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

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

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

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

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

</Target>

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

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

Ответ 1

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

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

Привет

Jesper Hauge

Ответ 2

Следующий код поступает из пакета 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()

uninstall.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()
}

Пример целевых файлов - файл, который копирует некоторые файлы в выходной путь

<?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>