我意识到这是一个老问题,但找出解决方案很乏味。因此,在这里发布我的发现是为了(希望)为其他人节省大量时间。
解决方案 1(推荐)
现在 MSBuild在 GitHub 上开源,我在他的 MSBuild 示例 repo 上向 MSFT 团队成员 (Jeff Kluge) 询问了一个类似的问题(例外是,我正在尝试使用内联任务),并收到了一个解决方案:https://github。 com/jeffkl/MSBuild-NetCore/issues/2
@jeffkl 说:
这是我的示例:https ://github.com/jeffkl/MSBuild-NetCore/blob/master/src/OutputPathViaInlineTask/build.targets
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="GetOutputPath" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<OutputPath ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs">
<![CDATA[
OutputPath = Path.Combine("bin", Guid.NewGuid().ToString("N")) + System.IO.Path.DirectorySeparatorChar;
]]>
</Code>
</Task>
</UsingTask>
<Target Name="SetOutputPath"
BeforeTargets="_CheckForInvalidConfigurationAndPlatform">
<Message Text="Before:" />
<Message Text=" OutputPath: '$(OutputPath)'" />
<Message Text=" OutDir: '$(OutDir)'" />
<Message Text=" PublishDir: '$(PublishDir)'" />
<Message Text=" _InvalidConfigurationError: '$(_InvalidConfigurationError)'" />
<Message Text=" _InvalidConfigurationWarning: '$(_InvalidConfigurationWarning)'" />
<GetOutputPath>
<Output TaskParameter="OutputPath" PropertyName="OutputPath"/>
<!--
OutDir is set in Microsoft.Common.CurrentVersion.targets as a copy of $(OutputPath). Since
we've reset $(OutputPath), we need to reset $(OutDir) as well for backwards compatibility.
-->
<Output TaskParameter="OutputPath" PropertyName="OutDir" />
</GetOutputPath>
<PropertyGroup>
<!--
PublishDir is set in Microsoft.Common.CurrentVersion.targets and starts with $(OutputPath).
Since we've reset $(OutputPath), we need to reset $(PublishDir). We have to do this in a
<PropertyGroup /> because the <Output /> from <GetOutputPath /> can't append text.
-->
<PublishDir>$(OutputPath)app.publish\</PublishDir>
<!--
If <OutputPath /> is not set in a top-level <PropertyGroup /> then $(_InvalidConfigurationError)
is set to 'true' which will cause a build error. However, we've set $(OutputPath) in a task
just before _CheckForInvalidConfigurationAndPlatform ran so we can turn off the error now that
we know everything is set properly.
-->
<_InvalidConfigurationError>false</_InvalidConfigurationError>
<_InvalidConfigurationWarning>false</_InvalidConfigurationWarning>
</PropertyGroup>
<Message Text="After:" />
<Message Text=" OutputPath: '$(OutputPath)'" />
<Message Text=" OutDir: '$(OutDir)'" />
<Message Text=" PublishDir: '$(PublishDir)'" />
<Message Text=" _InvalidConfigurationError: '$(_InvalidConfigurationError)'" />
<Message Text=" _InvalidConfigurationWarning: '$(_InvalidConfigurationWarning)'" />
</Target>
</Project>
@jeffkl 说:
此处导入:https ://github.com/jeffkl/MSBuild-NetCore/blob/master/src/OutputPathViaInlineTask/OutputPathViaInlineTask.csproj#L24
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C76AA0AA-3B50-48D6-BE46-0F2D8DC56C02}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>OutputPathViaInlineTask</RootNamespace>
<AssemblyName>OutputPathViaInlineTask</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "/>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "/>
<ItemGroup>
<Reference Include="System" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildThisFileDirectory)build.targets" />
</Project>
请注意,此解决方案不限于 .NET Core (MSBuild 15.0+)。我已经使用 MSBuild 14.0 (VS2015) 进行了测试,并且可以正常工作。:)
解决方案 2
我们还可以使用MSBuild 属性函数。它提供了一组有限/列入白名单的 BCL API 方法,并且需要一个外部环境变量来加载自定义程序集。请注意,我们不能System.Enviornment.SetEnvironmentVariable
在我们的目标/项目文件中使用,因为它不在白名单中(仅System.Enviornment.GetEnvironmentVariable
在)。因此,它需要在构建解决方案(甚至在 VS 中打开解决方案)之前对环境进行外部更改。从命令行会更容易一些:
# cmd
set MSBUILDENABLEALLPROPERTYFUNCTIONS=1 && msbuild my.sln
# PowerShell
$env:MSBUILDENABLEALLPROPERTYFUNCTIONS=1 ; msbuild my.sln
# UnixShell
MSBUILDENABLEALLPROPERTYFUNCTIONS=1 dotnet build my.sln
有关使用、限制及其解决方法的更多详细信息,请参阅https://blogs.msdn.microsoft.com/visualstudio/2010/04/02/msbuild-property-functions/ 。