如何创建一个 msbuild 目标以在“运行”目标(dotnet 运行)之后运行?
Posted
技术标签:
【中文标题】如何创建一个 msbuild 目标以在“运行”目标(dotnet 运行)之后运行?【英文标题】:How to create a msbuild target to run after "Run" target (dotnet run)? 【发布时间】:2021-09-30 05:43:05 【问题描述】:我正在尝试创建一个 msbuild csproj,我可以在其中调用 dotnet run myproject
并在执行后删除 bin/obj 文件夹。 但是,CustomAfterRun
目标(如下)不会在 Run 目标之后执行。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
<Target Name="CustomAfterRun" AfterTargets="Run">
<Message Importance="high" Text="[msbuild] Cleaning bin and obj..."/>
<RemoveDir Directories="$(TargetDir)" />
<RemoveDir Directories="$(ProjectDir)$(BaseIntermediateOutputPath)" />
</Target>
</Project>
如果我创建一个目标CustomAfterBuild
(使用AfterTargets="Build"
),它可以正常工作(当我运行dotnet build myproj
时它会在构建后执行)。
这是一个错误还是我做错了什么?
还有最疯狂的部分:如果在CustomAfterBuild
内部调用<CallTarget Targets="Run" />
,那么在构建之后调用我的程序,在这种情况下CustomAfterRun
运行良好!这种方法的缺点是程序输出只有在我启用详细的详细级别时才可见,并且在 CustomAfterRun
运行(删除 bin/obj 文件夹)之后,它也会尝试再次运行程序(意味着运行目标是两次调用?!)给我一个错误:System.ComponentModel.Win32Exception (2): The system cannot find the file specified.
。
编辑:作为替代方案,我也尝试覆盖 Run 目标,但这根本不起作用:
<Project>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
<Target Name="Run" >
<Message Importance="high" Text="[msbuild] overriden..."/>
</Target>
</Project>
【问题讨论】:
【参考方案1】:原来我对dotnet run
有一个错误的假设。
dotnet msbuild
基本上是调用msbuild 的外观。 dotnet build
只是dotnet msbuild -restore
的快捷方式,因此它将恢复 nuget 包并构建(默认目标)。 dotnet clean
也调用 msbuild(干净的目标)。
在类似的意义上我期待 dotnet run
使用来自 msbuild 的 Run
目标,但它没有。它调用dotnet msbuild
(如果需要),但它会使用 msbuild 运行输出 WITHOUT。
如果我运行msbuild -target:Run
,运行后的事件就可以正常工作!
因此,一种可能的解决方案是使用普通的 msbuild。
例如:dotnet msbuild /t:Restore;Build;Run;Clean MyProj.csproj
),
但是,另一个让我烦恼的行为是,当通过 msbuild 启动程序时,我在控制台输出中看不到颜色(如果有的话)。这可能是因为 msbuild 使用控制台重定向来运行我的程序。 dotnet run
幸好没有这种行为,所以我的最终解决方案是:
dotnet run & dotnet clean
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
<!-- Clean is not so perfect, clear leftovers -->
<Target Name="CleanBinObj" AfterTargets="Clean">
<RemoveDir Directories="$(ProjectDir)$(BaseOutputPath)" />
<RemoveDir Directories="$(ProjectDir)$(BaseIntermediateOutputPath)" />
</Target>
<!-- If someone uses msbuild to launch, force a clean.. -->
<Target Name="CustomAfterRun" AfterTargets="Run">
<CallTarget Targets="Clean" />
</Target>
</Project>
或者对于我的特定情况,我将在同一个文件夹中保留多个单独的 cs 程序(每个都有自己的 csproj),并且我想用我的文件的单独(临时)文件夹覆盖 bin/obj 文件夹:
<Project>
<PropertyGroup>
<TempDir>$(MSBuildProjectName).cs.tmp\</TempDir>
<BaseOutputPath>$(TempDir)</BaseOutputPath>
<BaseIntermediateOutputPath>$(TempDir)</BaseIntermediateOutputPath>
</PropertyGroup>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
<!-- Clean is not so perfect, clear leftovers -->
<Target Name="CleanBinObj" AfterTargets="Clean">
<Message Importance="high" Text="Cleaning $(TempDir) (bin/obj)..."/>
<RemoveDir Directories="$(TempDir)" />
</Target>
<!-- If someone uses msbuild to launch, force a clean.. -->
<Target Name="CustomAfterRun" AfterTargets="Run">
<CallTarget Targets="Clean" />
</Target>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>
【讨论】:
以上是关于如何创建一个 msbuild 目标以在“运行”目标(dotnet 运行)之后运行?的主要内容,如果未能解决你的问题,请参考以下文章
在 MSBuild 中为数据库项目使用 PublishProfile
如何创建命令以在 Windows Batch 中运行其他应用程序? [关闭]