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

时间:2011-06-13 10:00:15

标签: powershell msbuild nuget csproj

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

  1. 将新目标添加到csproj文件中(MyCustomBeforeBuildTarget)
  2. 添加BeforeBuild目标(如果尚未存在)
  3. 编辑BeforeBuild DependsOnTargets属性以包含我的自定义目标
  4. 安装完成后,我的csproj应该包含以下内容:

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

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

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

2 个答案:

答案 0 :(得分:13)

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

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

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

然后,您需要将install.ps1文件放在NuGet包的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()

应该是它。

此致

Jesper Hauge

答案 1 :(得分:8)

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

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

下载该软件包并使用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()

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>