【问题标题】:Create a custom powershell script for nuget that adds a custom target to the csproj BeforeBuild step为 nuget 创建自定义 powershell 脚本,将自定义目标添加到 csproj BeforeBuild 步骤
【发布时间】:2011-09-13 19:30:06
【问题描述】:

我想创建一个 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 脚本 here 可能是解决方案的一部分,但我没有足够的 PowerShell 经验来知道如何实际使用它们来编辑 csproj。

【问题讨论】:

    标签: powershell msbuild nuget csproj


    【解决方案1】:

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

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

    下载包并使用NuGetPackageExplorer打开它,看看它是如何完成的。

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

    (我找不到任何 powershell-highlighting,所以我改用 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>
    

    【讨论】:

    • 这很棒。我希望我的目标文件在项目中,所以我这样做是为了在安装中获取 $TargetsPath: $fileInfo = new-object -typename System.IO.FileInfo -ArgumentList $Project.FullName; $projectDirectory = $fileInfo.DirectoryName; $TargetsFile = 'solutionBinFilesForAdmincenter.targets; $TargetsPath = $projectDirectory | Join-Path -ChildPath $TargetsFile
    【解决方案2】:

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

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

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

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

    应该是这样的。

    问候

    杰斯珀·豪格

    【讨论】:

    • 我使用了这种方法,但遇到了以下问题。如果您的解决方案中有多个项目并且您使用 UI(项目右键单击 -> 管理 NuGet 包),则 Get-MSBuildProject 返回的不是您单击的项目,而是在包管理器控制台中选择的项目。使用项目名称可以解决此问题:$buildProject = Get-MSBuildProject $project.ProjectName
    • 在任何地方都有 NuGetPowerTools 的文档吗?好像没有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2019-02-14
    • 2022-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多