13

我想创建一个 nuget 包,使用我创建的自定义 MSBuild 任务将 BeforeBuild 步骤添加到我的 csproj。理想情况下,我想:

  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。

4

2 回答 2

13

NuGetPowerTools是一个包,添加了一些 PowerShell 函数,可以更轻松地处理要添加包的项目的项目设置。要使用可用的功能,您只需使您的包依赖于 NuGetPowerTools,使用包 nuspec 文件中的依赖项标记,如下所示:

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

这将使获取对项目的构建项目表示的引用成为可能。

然后你需要在你的 NuGet 包的文件夹中放置一个install.ps1文件tools,这个 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()

应该是这样的。

问候

杰斯珀豪格

于 2011-09-08T07:19:51.053 回答
9

以下代码来自名为 CodeAssassin.WixWebProjectReferences 的包。它在安装和卸载时向项目文件添加和删除以下导入标签。该软件包不需要任何依赖项。

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

下载包并使用NuGetPackageExplorer打开它以了解它是如何完成的。

下面是来自 install.ps1 和 uninstall.ps1 的代码(它们仅在 NuGet 包的内容文件夹非空时执行)。

(我找不到任何 powershell 高亮显示,所以我改用 php,但它并不完美。)

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

将一些文件复制到输出路径的示例目标文件

<?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>
于 2012-08-27T21:57:07.673 回答