我正在创建一个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="<# /* AUTOGENERATED FILE */ #>" Overwrite="true" Encoding="Unicode" />
<!-- T4Toolbox -->
<WriteLinesToFile File="@(TargetReferenceFile)" Lines="<#@ include file="T4Toolbox.tt" #>" Overwrite="false" Encoding="Unicode" />
<WriteLinesToFile File="@(TargetReferenceFile)" Lines="<#@ assembly name="" completion="T4Toolbox.dll" #>" Overwrite="false" Encoding="Unicode" />
<!-- Visual Studio IDE -->
<WriteLinesToFile File="@(TargetReferenceFile)" Lines="<#@ assembly name="EnvDTE, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" #>" Overwrite="false" Encoding="Unicode" />
<WriteLinesToFile File="@(TargetReferenceFile)" Lines="<#@ assembly name="EnvDTE80, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" #>" Overwrite="false" Encoding="Unicode" />
<WriteLinesToFile File="@(TargetReferenceFile)" Lines="<#@ assembly name="VSLangProj, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" #>" Overwrite="false" Encoding="Unicode" />
<WriteLinesToFile File="@(TargetReferenceFile)" Lines="<#@ assembly name="Microsoft.VisualStudio.Shell.Interop.8.0, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" #>" Overwrite="false" Encoding="Unicode" />
<WriteLinesToFile File="@(TargetReferenceFile)" Lines="<#@ assembly name="Microsoft.VisualStudio.TextTemplating.Interfaces.10.0, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" #>" Overwrite="false" Encoding="Unicode" />
<WriteLinesToFile File="@(TargetReferenceFile)" Lines="<#@ assembly name="Microsoft.VisualStudio.TextTemplating.12.0, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" #>" Overwrite="false" Encoding="Unicode" />
<!-- With HintPath -->
<WriteLinesToFile File="@(TargetReferenceFile)" Lines="<#@ assembly name="%24%28ProjectDir%29%(Reference.HintPath)" #>" Overwrite="false" Encoding="Unicode" Condition="'%(Reference.HintPath)' != '' And $([System.String]::new('%(Reference.HintPath)').Contains('T4Toolbox.dll')) == 'false'" />
<!-- Without HintPath -->
<WriteLinesToFile File="@(TargetReferenceFile)" Lines="<#@ assembly name="%(Reference.Identity)" #>" Overwrite="false" Encoding="Unicode" Condition="'%(Reference.HintPath)' == ''" />
<!-- ProjectReference -->
<WriteLinesToFile File="@(TargetReferenceFile)" Lines="<#@ assembly name="%24%28ProjectDir%29%(ProjectReference.RelativeDir)bin\$(Configuration)\%(ProjectReference.Name).dll" #>" Overwrite="false" Encoding="Unicode" Condition="'%(ProjectReference.Name)' != ''" />
<!-- Includes -->
<WriteLinesToFile File="@(IncludesFile)" Lines="<# /* AUTOGENERATED FILE */ #>" Overwrite="true" Encoding="Unicode" />
<WriteLinesToFile File="@(IncludesFile)" Lines="<#@ include file="..\Includes\%(Includes.Filename)%(Includes.Extension)" #>" Overwrite="false" Encoding="Unicode" />
<Message Text="Generating %(TargetReferenceFile.FullPath) &%(IncludesFile.FullPath)" Importance="high" />
</Target>
</Project>
答案 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脚本。它们旨在为您提供指向正确实现的指针。