NuGet包:安装时运行MSBUILD

时间:2015-01-26 16:41:06

标签: msbuild nuget

我正在创建一个NuGet包,并且在安装包时会将.targets文件安装到目标.csproj文件中。这可以完美地按预期工作,.targets文件具有目标元素,该元素在Build和TransformOnBuild目标之前执行。

但是,我现在要做的是在安装软件包后执行此目标。也就是说,我不希望用户在安装我的包后必须手动构建他们的.csproj。我希望软件包安装在将软件包安装到目标项目后运行此定义的目标

原因是目标会自动生成目标项目中的一些文件(并且基于目标项目中的属性),我希望使用初始数据生成这些文件在安装时,不要等到用户构建该项目以创建数据。

FWIW,我发现的最接近这个的问题就是这个:Configure NuGet package to add a build event when installed,但这是针对构建管道的。我想在NuGet项目安装后启动构建(我的目标在.targets文件中)。

修改

感谢@ matt-ward我能够获得最终答案。我在这里分享完整的答案。它以递归方式遍历项目以查找任何.tt文件,并将其自定义工具设置为空白,然后编译项目以生成所需的工件。这是完整的install.ps1:

# Runs every time a package is installed in a project

param($installPath, $toolsPath, $package, $project)

# $installPath is the path to the folder where the package is installed.
# $toolsPath is the path to the tools directory in the folder where the package is installed.
# $package is a reference to the package object.
# $project is a reference to the project the package was installed to.


function AdjustCustomTool( $folder )
{
    foreach ( $i in $folder.ProjectItems )
    {
        switch ( $i.Kind ) 
        { 
            "{6BB5F8EF-4483-11D3-8BCF-00C04F8EC28C}" # Folder
            {
                AdjustCustomTool( $i );
                break;
            } 
            "{6BB5F8EE-4483-11D3-8BCF-00C04F8EC28C}" # File
            {
                switch ( [System.IO.Path]::GetExtension( $i.Name ) )
                {
                    ".tt"
                    {
                        $i.Properties.Item("CustomTool").Value = "";
                        break;
                    }
                }
            }
        }       
    }
}
$templates = $project.ProjectItems.Item( "DragonSpark.Templates" );
AdjustCustomTool( $templates );

# Need to load MSBuild assembly if it's not loaded yet.
Add-Type -AssemblyName 'Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'

# Grab the loaded MSBuild project for the project
$project = [Microsoft.Build.Evaluation.ProjectCollection]::GlobalProjectCollection.GetLoadedProjects($project.FullName) | Select-Object -First 1
$project.Build( "GenerateTemplateReferences" );

FWIW,这是我的.targets文件:                                                                                                             

        <Error Condition="'@(TargetReferenceFile -> Count())' == 0" Text="No DragonSpark.Templates\Generated\References.tt file found" />
        <Error Condition="'@(IncludesFile -> Count())' == 0" Text="No DragonSpark.Templates\Generated\Includes.tt file found" />

        <WriteLinesToFile File="@(TargetReferenceFile)" Lines="&lt;# /* AUTOGENERATED FILE */ #&gt;" Overwrite="true" Encoding="Unicode" />

        <!-- T4Toolbox -->
        <WriteLinesToFile File="@(TargetReferenceFile)" Lines="&lt;#@ include file=&quot;T4Toolbox.tt&quot; #&gt;" Overwrite="false" Encoding="Unicode" />
        <WriteLinesToFile File="@(TargetReferenceFile)" Lines="&lt;#@ assembly name=&quot;&quot; completion=&quot;T4Toolbox.dll&quot; #&gt;" Overwrite="false" Encoding="Unicode" />

        <!-- Visual Studio IDE -->
        <WriteLinesToFile File="@(TargetReferenceFile)" Lines="&lt;#@ assembly name=&quot;EnvDTE, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&quot; #&gt;" Overwrite="false" Encoding="Unicode" />
        <WriteLinesToFile File="@(TargetReferenceFile)" Lines="&lt;#@ assembly name=&quot;EnvDTE80, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&quot; #&gt;" Overwrite="false" Encoding="Unicode" />
        <WriteLinesToFile File="@(TargetReferenceFile)" Lines="&lt;#@ assembly name=&quot;VSLangProj, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&quot; #&gt;" Overwrite="false" Encoding="Unicode" />
        <WriteLinesToFile File="@(TargetReferenceFile)" Lines="&lt;#@ assembly name=&quot;Microsoft.VisualStudio.Shell.Interop.8.0, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a&quot; #&gt;" Overwrite="false" Encoding="Unicode" />
        <WriteLinesToFile File="@(TargetReferenceFile)" Lines="&lt;#@ assembly name=&quot;Microsoft.VisualStudio.TextTemplating.Interfaces.10.0, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL&quot; #&gt;" Overwrite="false" Encoding="Unicode" />
        <WriteLinesToFile File="@(TargetReferenceFile)" Lines="&lt;#@ assembly name=&quot;Microsoft.VisualStudio.TextTemplating.12.0, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL&quot; #&gt;" Overwrite="false" Encoding="Unicode" />

        <!-- With HintPath -->
        <WriteLinesToFile File="@(TargetReferenceFile)" Lines="&lt;#@ assembly name=&quot;%24%28ProjectDir%29%(Reference.HintPath)&quot; #&gt;" Overwrite="false" Encoding="Unicode" Condition="'%(Reference.HintPath)' != '' And $([System.String]::new('%(Reference.HintPath)').Contains('T4Toolbox.dll')) == 'false'" />

        <!-- Without HintPath -->
        <WriteLinesToFile File="@(TargetReferenceFile)" Lines="&lt;#@ assembly name=&quot;%(Reference.Identity)&quot; #&gt;" Overwrite="false" Encoding="Unicode" Condition="'%(Reference.HintPath)' == ''" />

        <!-- ProjectReference -->
        <WriteLinesToFile File="@(TargetReferenceFile)" Lines="&lt;#@ assembly name=&quot;%24%28ProjectDir%29%(ProjectReference.RelativeDir)bin\$(Configuration)\%(ProjectReference.Name).dll&quot; #&gt;" Overwrite="false" Encoding="Unicode" Condition="'%(ProjectReference.Name)' != ''" />

        <!-- Includes -->
        <WriteLinesToFile File="@(IncludesFile)" Lines="&lt;# /* AUTOGENERATED FILE */ #&gt;" Overwrite="true" Encoding="Unicode" />
        <WriteLinesToFile File="@(IncludesFile)" Lines="&lt;#@ include file=&quot;..\Includes\%(Includes.Filename)%(Includes.Extension)&quot; #&gt;" Overwrite="false" Encoding="Unicode" />

        <Message Text="Generating %(TargetReferenceFile.FullPath) &amp;%(IncludesFile.FullPath)" Importance="high" />
    </Target>
</Project>

1 个答案:

答案 0 :(得分:0)

您可以使用PowerShell脚本(install.ps1)在安装NuGet包后运行构建。

PowerShell脚本可以使用Visual Studio API进行构建。类似于以下内容的东西将构建项目:

param($installPath, $toolsPath, $package, $project)

$config = $dte.Solution.SolutionBuild.ActiveConfiguration.Name
$dte.Solution.SolutionBuild.BuildProject($config, $project.UniqueName, $false)

构建特定的MSBuild目标更加棘手。你可以直接调用MSBuild.exe。这是PostSharp NuGet package所做的事情。或者您可以使用MSBuild API来构建特定目标。类似的东西:

Add-Type -AssemblyName 'Microsoft.Build, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'

# Grab the loaded MSBuild project for the project
$buildProject = [Microsoft.Build.Evaluation.ProjectCollection]::GlobalProjectCollection.GetLoadedProjects($project.FullName) | Select-Object -First 1

$buildProject.Build("YourTargetName")

请注意,我尚未测试这些PowerShell脚本。它们旨在为您提供指向正确实现的指针。