为nuget创建自定义PowerShell脚本,将自定义目标添加到csproj BeforeBuild步骤

Mar*_*ath 11 msbuild powershell csproj nuget

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

  1. 将新Target添加到csproj文件中(MyCustomBeforeBuildTarget)
  2. 添加BeforeBuild目标(如果尚未存在)
  3. 编辑BeforeBuild DependsOnTargets属性以包含我的自定义目标

所以安装完成后我的csproj应该包含以下内容:

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

</Target>
Run Code Online (Sandbox Code Playgroud)

此外,当我的包被删除时,自定义目标也会消失,这将是很好的,虽然我添加了一个条件,如果我的自定义任务DLL不存在,它应该使它忽略目标.

我可以写的最简单的Powershell nuget安装脚本是什么,它将添加我的自定义目标?我觉得这里的PowerShell脚本可能是解决方案的一部分,但我没有足够的PowerShell经验知道如何实际使用它们来编辑csproj.

Hau*_*uge 13

NuGetPowerTools是增加了一些PowerShell函数,使得它更容易与您要添加一个包到项目的项目设置工作包.要使用可用的功能,您只需要使用包nuspec文件中的dependencies标记使您的包依赖于NuGetPowerTools,如下所示:

<dependencies>
  <dependency id="NuGetPowerTools" version="0.26" />
</dependencies>
Run Code Online (Sandbox Code Playgroud)

这样就可以获取对项目的构建项目表示的引用.

然后,您需要将一个install.ps1文件放在toolsNuGet包的文件夹中,此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()
Run Code Online (Sandbox Code Playgroud)

那应该是它.

问候

Jesper Hauge

  • 我使用这种方法,我遇到了以下问题.如果您的解决方案中有多个项目并且您使用UI(项目右键单击 - >管理NuGet包),那么`Get-MSBuildProject`不会返回您单击的项目,而是返回在Package Manager Console中选择的项目.它就像使用项目名称修复了这个问题:`$ buildProject = Get-MSBuildProject $ project.ProjectName` (2认同)

小智 8

以下代码来自名为CodeAssassin.WixWebProjectReferences的包.它在安装和卸载时添加并删除以下import-tag到项目文件.该包不需要任何依赖项.

<Import Project="..\packages\CodeAssassin.WixWebProjectReferences.1.0\tools\CodeAssassin.WixWebProjectReferences.targets" />
Run Code Online (Sandbox Code Playgroud)

下载该软件包并使用NuGetPackageExplorer打开它以了解它是如何完成的.

下面是install.ps1和uninstall.ps1中的代码(只有在NuGet-package的内容文件夹非空时才会执行它们).

(我找不到任何powershell-highlighting,所以我使用了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()
Run Code Online (Sandbox Code Playgroud)

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()
}
Run Code Online (Sandbox Code Playgroud)

示例目标文件,用于将某些文件复制到输出路径

<?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>
Run Code Online (Sandbox Code Playgroud)