msbuild 相关问题

Microsoft Build Engine,也称为MSBuild,是托管代码的构建平台,是.NET Framework的一部分。

编译时检测目标框架版本

我有一些使用扩展方法的代码,但使用VS2008中的编译器在.NET 2.0下编译。为了促进这一点,我必须声明 ExtensionAttribute: /// /// 我有一些使用扩展方法的代码,但使用 VS2008 中的编译器在 .NET 2.0 下编译。为了促进这一点,我必须声明 ExtensionAttribute: /// <summary> /// ExtensionAttribute is required to define extension methods under .NET 2.0 /// </summary> public sealed class ExtensionAttribute : Attribute { } 但是,我现在希望包含该类的库也可以在 .NET 3.0、3.5 和 4.0 下编译 - 没有“ExtensionAttribute 在多个位置定义”警告。 当目标框架版本是 .NET 2 时,是否可以使用任何编译时指令来仅包含 ExtensionAttribute? 带有“创建 N 个不同配置”的链接 SO 问题当然是一种选择,但是当我需要这个时,我只是添加了条件 DefineConstants 元素,因此在我的 Debug|x86 (例如)中,在 DEBUG;TRACE 的现有 DefineConstants 之后,我添加了这 2 个,检查在 csproj 文件的第一个 PropertyGroup 中设置的 TFV 中的值。 <DefineConstants Condition=" '$(TargetFrameworkVersion)' == 'v4.0' ">RUNNING_ON_4</DefineConstants> <DefineConstants Condition=" '$(TargetFrameworkVersion)' != 'v4.0' ">NOT_RUNNING_ON_4</DefineConstants> 显然,你不需要两者,但它只是提供 eq 和 ne 行为的示例 - #else 和 #elif 也可以正常工作:) class Program { static void Main(string[] args) { #if RUNNING_ON_4 Console.WriteLine("RUNNING_ON_4 was set"); #endif #if NOT_RUNNING_ON_4 Console.WriteLine("NOT_RUNNING_ON_4 was set"); #endif } } 然后我可以在目标 3.5 和 4.0 之间切换,它会做正确的事情。 我有一些改进目前给出的答案的建议: 使用 Version.CompareTo()。相等性测试不适用于尚未命名的更高版本的框架。例如 <CustomConstants Condition=" '$(TargetFrameworkVersion)' == 'v4.0' "> 与您通常想要的 v4.5 或 v4.5.1 不匹配。 使用导入文件,这样这些附加属性只需定义一次。我建议将导入文件置于源代码控制之下,以便更改与项目文件一起传播,而不需要额外的努力。 在项目文件的末尾添加导入元素,以便它独立于任何配置特定的属性组。这还有一个好处是需要在项目文件中添加一行。 这是导入文件(VersionSpecificSymbols.Common.prop) <!-- ****************************************************************** Defines the Compile time symbols Microsoft forgot Modelled from https://msdn.microsoft.com/en-us/library/ms171464.aspx ********************************************************************* --> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <DefineConstants Condition="$([System.Version]::Parse('$(TargetFrameworkVersion.Substring(1))').CompareTo($([System.Version]::Parse('4.5.1')))) &gt;= 0">$(DefineConstants);NETFX_451</DefineConstants> <DefineConstants Condition="$([System.Version]::Parse('$(TargetFrameworkVersion.Substring(1))').CompareTo($([System.Version]::Parse('4.5')))) &gt;= 0">$(DefineConstants);NETFX_45</DefineConstants> <DefineConstants Condition="$([System.Version]::Parse('$(TargetFrameworkVersion.Substring(1))').CompareTo($([System.Version]::Parse('4.0')))) &gt;= 0">$(DefineConstants);NETFX_40</DefineConstants> <DefineConstants Condition="$([System.Version]::Parse('$(TargetFrameworkVersion.Substring(1))').CompareTo($([System.Version]::Parse('3.5')))) &gt;= 0">$(DefineConstants);NETFX_35</DefineConstants> <DefineConstants Condition="$([System.Version]::Parse('$(TargetFrameworkVersion.Substring(1))').CompareTo($([System.Version]::Parse('3.0')))) &gt;= 0">$(DefineConstants);NETFX_30</DefineConstants> </PropertyGroup> </Project> 将导入元素添加到项目文件 通过在末尾、标记之前添加来从 .csproj 文件中引用它。 … <Import Project="VersionSpecificSymbols.Common.prop" /> </Project> 您需要修复路径以指向放置此文件的公共/共享文件夹。 使用编译时符号 namespace VersionSpecificCodeHowTo { using System; internal class Program { private static void Main(string[] args) { #if NETFX_451 Console.WriteLine("NET_451 was set"); #endif #if NETFX_45 Console.WriteLine("NET_45 was set"); #endif #if NETFX_40 Console.WriteLine("NET_40 was set"); #endif #if NETFX_35 Console.WriteLine("NETFX_35 was set"); #endif #if NETFX_30 Console.WriteLine("NETFX_30 was set"); #endif #if NETFX_20 Console.WriteLine("NETFX_20 was set"); #else The Version specific symbols were not set correctly! #endif #if DEBUG Console.WriteLine("DEBUG was set"); #endif #if MySymbol Console.WriteLine("MySymbol was set"); #endif Console.ReadKey(); } } } 一个常见的“现实生活”例子 在.NET 4.0之前实现Join(字符串分隔符,IEnumerable字符串) // string Join(this IEnumerable<string> strings, string delimiter) // was not introduced until 4.0. So provide our own. #if ! NETFX_40 && NETFX_35 public static string Join( string delimiter, IEnumerable<string> strings) { return string.Join(delimiter, strings.ToArray()); } #endif 参考文献 属性函数 MSBuild 属性评估 我可以根据 .NET Framework 版本制作预处理器指令吗? C#中根据框架版本进行条件编译 属性组仅被覆盖,因此这会取消您对 DEBUG、TRACE 或任何其他设置的设置。 - 请参阅MSBuild 属性评估 此外,如果从命令行设置 DefineConstants 属性,则您在项目文件中对其执行的任何操作都无关紧要,因为该设置将变为全局只读。这意味着您对该值的更改会默默失败。 维护现有已定义常量的示例: <CustomConstants Condition=" '$(TargetFrameworkVersion)' == 'v2.0' ">V2</CustomConstants> <CustomConstants Condition=" '$(TargetFrameworkVersion)' == 'v4.0' ">V4</CustomConstants> <DefineConstants Condition=" '$(DefineConstants)' != '' And '$(CustomConstants)' != '' ">$(DefineConstants);</DefineConstants> <DefineConstants>$(DefineConstants)$(CustomConstants)</DefineConstants> 本节必须位于任何其他定义的常量之后,因为这些常量不太可能以附加方式设置 我只定义了这两个,因为这是我对我的项目最感兴趣的,ymmv。 另请参阅:常见的 MsBuild 项目属性 目标框架的预定义符号现已内置到 dotnet 工具和 VS 2017 及以后版本使用的 MSBuild 版本中。请参阅 https://learn.microsoft.com/en-us/dotnet/standard/frameworks#how-to-specify-a-target-framework 了解完整列表。 #if NET47 Console.WriteLine("Running on .Net 4.7"); #elif NETCOREAPP2_0 Console.WriteLine("Running on .Net Core 2.0"); #endif 我想贡献一个更新的答案来解决一些问题。 如果您设置 DefineConstants 而不是 CustomConstants,在进行某些框架版本切换后,您最终会在条件编译符号调试命令行中出现重复的条件常量(即:NETFX_451;NETFX_45;NETFX_40;NETFX_35;NETFX_30;NETFX_20;NETFX_35; NETFX_30;NETFX_20;)。 这是解决任何问题的 VersionSpecificSymbols.Common.prop。 <!-- ********************************************************************* Defines the Compile time symbols Microsoft forgot Modelled from https://msdn.microsoft.com/en-us/library/ms171464.aspx ********************************************************************* Author: Lorenzo Ruggeri ([email protected]) --> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Choose> <When Condition=" $(TargetFrameworkVersion) == 'v2.0' "> <PropertyGroup> <CustomConstants >$(CustomConstants);NETFX_20</CustomConstants> </PropertyGroup> </When> <When Condition=" $(TargetFrameworkVersion) == 'v3.0' "> <PropertyGroup> <CustomConstants >$(CustomConstants);NETFX_30</CustomConstants> <CustomConstants >$(CustomConstants);NETFX_20</CustomConstants> </PropertyGroup> </When> <When Condition=" $(TargetFrameworkVersion) == 'v3.5' "> <PropertyGroup> <CustomConstants >$(CustomConstants);NETFX_35</CustomConstants> <CustomConstants >$(CustomConstants);NETFX_30</CustomConstants> <CustomConstants >$(CustomConstants);NETFX_20</CustomConstants> </PropertyGroup> </When> <Otherwise> <PropertyGroup> <CustomConstants Condition="$([System.Version]::Parse('$(TargetFrameworkVersion.Substring(1))').CompareTo($([System.Version]::Parse('4.5.1')))) &gt;= 0">$(CustomConstants);NETFX_451</CustomConstants> <CustomConstants Condition="$([System.Version]::Parse('$(TargetFrameworkVersion.Substring(1))').CompareTo($([System.Version]::Parse('4.5')))) &gt;= 0">$(CustomConstants);NETFX_45</CustomConstants> <CustomConstants Condition="$([System.Version]::Parse('$(TargetFrameworkVersion.Substring(1))').CompareTo($([System.Version]::Parse('4.0')))) &gt;= 0">$(CustomConstants);NETFX_40</CustomConstants> <CustomConstants Condition="$([System.Version]::Parse('$(TargetFrameworkVersion.Substring(1))').CompareTo($([System.Version]::Parse('3.5')))) &gt;= 0">$(CustomConstants);NETFX_35</CustomConstants> <CustomConstants Condition="$([System.Version]::Parse('$(TargetFrameworkVersion.Substring(1))').CompareTo($([System.Version]::Parse('3.0')))) &gt;= 0">$(CustomConstants);NETFX_30</CustomConstants> <CustomConstants Condition="$([System.Version]::Parse('$(TargetFrameworkVersion.Substring(1))').CompareTo($([System.Version]::Parse('2.0')))) &gt;= 0">$(CustomConstants);NETFX_20</CustomConstants> </PropertyGroup> </Otherwise> </Choose> <PropertyGroup> <DefineConstants>$(DefineConstants);$(CustomConstants)</DefineConstants> </PropertyGroup> </Project> 使用反射来判断类是否存在。如果是,则动态地创建并使用它,否则使用可以定义的.Net2解决方法类,但不用于所有其他.net版本。 这是我用于 AggregateException 的代码,仅适用于 .Net 4 及更高版本: var aggregatException = Type.GetType("System.AggregateException"); if (aggregatException != null) // .Net 4 or greater { throw ((Exception)Activator.CreateInstance(aggregatException, ps.Streams.Error.Select(err => err.Exception))); } // Else all other non .Net 4 or less versions throw ps.Streams.Error.FirstOrDefault()?.Exception ?? new Exception("Powershell Exception Encountered."); // Sanity check operation, should not hit. 适用于 .NET 5+(和 .NET Core) 您可以在编译时使用Preprocessor symbols,更有趣的一点是也可以使用GREATER版本: #if NET8_0_OR_GREATER Console.WriteLine("Running on .Net 8 or greater versions"); #elif NET6_0_OR_GREATER Console.WriteLine("Running on .Net 6 or greater versions"); #elif NETCOREAPP3_1_OR_GREATER Console.WriteLine("Running on .Net Core 3.1 or greater versions"); #endif 在此处查看更多选项: https://learn.microsoft.com/en-us/dotnet/standard/frameworks#preprocessor-symbols

回答 7 投票 0

MSBuild 项目中的参数化项

我们在程序集级别将 C# 自定义属性应用于一个解决方案中的数百个项目。它需要许多参数,这些参数是常量、构建时提供的值的混合...

回答 2 投票 0

Xamarin 形成无效的 Android 存档(无 .APK 文件)

我已经尝试了堆栈溢出中所有建议的解决方案。我在部署或构建解决方案时没有收到任何错误。每次构建都成功。 我正在使用 Visual Studio 2022 (p...

回答 4 投票 0

MSBuild如何传递要在CPP源文件中使用的参数?

我想在源文件中使用 MSBuild 参数,如下所示 msbuild /m /target:rebuild /p:Configuration=Debug /p:Platform=x64 /p:version_label=2019.12 rlabel.sln 我想加入...

回答 2 投票 0

AzureDevops 构建管道由于 donet 构建命令期间超时而被取消

我有一个构建管道,可以在 Azure Devops 中构建我的 .net 5 解决方案项目。到目前为止它运行良好,但最近由于超时而在构建阶段开始失败。构建命令...

回答 1 投票 0

使在 MSBuild 目标中创建的 ItemGroup 可用于调用目标

如果我的 MSBuild 文件中有以下目标: 如果我的 MSBuild 文件中有以下目标: <Target Name="Temp"> <CallTarget Targets="CreateTestList" /> <Message Text="TestList: -- @(TestAssembly) -- " /> <Message Text="Testing &quot;%(TestAssembly.Identity)&quot;" /> </Target> <Target Name="CreateTestList"> <CreateItem Include="**\bin\$(Configuration)\*Tests.dll"> <Output TaskParameter="Include" ItemName="TestAssembly" /> </CreateItem> <Message Text="TestList: -- @(TestAssembly) -- " /> <Message Text="Testing &quot;%(TestAssembly.Identity)&quot;" /> </Target> 如何使 Temp 目标中的 Message 语句打印出 CreateTestList 目标放入 @(TestAssembly) ItemGroup 中的项目? 有两点需要注意。首先,CreateItem 任务基本上已经过时了。只需在目标中声明一个 ItemGroup 即可使其更具可读性。其次,由于 MSBuild 发布项目的方式,您需要使 CreateTestList 目标作为依赖项运行,而不是与 CallTarget 一起运行,后者在大多数情况下用处有限。所以, <Target Name="Temp" DependsOnTargets="CreateTestList"> <Message ... </Target> <Target Name="CreateTestList"> <ItemGroup> <TestAssembly Include="**\bin\$(Configuration)\*Tests.dll"> </ItemGroup> <Message ... </Target>

回答 1 投票 0

如何指定RootNamespace所在的目录?

如果我有一个带有 RootNamespace AwesomeRoot 的项目,并且我希望一个类直接位于该命名空间中,我一直这样做的方法是将类的代码文件直接放入项目中

回答 1 投票 0

从智能感知构建中排除 MsBuild 目标

我已将自定义目标添加到 .csproj 文件中。 我希望当 Visual Studio 运行构建以向 Intellisense 提供输入时,不要调用该目标。 我已经寻找了一个房产......

回答 1 投票 0

如何向 SonarQube.Scanner.MSBuild.exe 提供参数?

通过在线搜索和查看sonarqube文档,我唯一能找到的是: SonarQube.Scanner.MSBuild.exe /k:KeyOfProject /n:NameOfProject msbuild.exe C:\projectpath\soultion.sln 声纳Q...

回答 1 投票 0

如何在 C#8.0 中使用 BuildManager?

我有一个 .csproj 配置如下: 执行 net8.0 我有一个 .csproj 配置如下: <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> </Project> 当我使用以下 msbuild 命令时,我可以构建项目。 msbuild MyProject.csproj /t:Restore;Rebuild;Publish /p:PublishSingleFile=True /p:SelfContained=True /p:PublishProtocol=FileSystem /p:Configuration=Release /p:PublishDir=bin\Release\Test /p:RuntimeIdentifier=win-x86 /p:PublishReadyToRun=False /p:PublishTrimmed=False 但是我想使用 BuildManager 来代替。 我尝试过以下代码: var properties = new Dictionary<string, string> { ["Configuration"] = "Release", ["Platform"] = "x86", ["RuntimeIdentifier"] = "win-x86", ["SelfContained"] = "True", ["PublishSingleFile"] = "True", ["PublishReadyToRun"] = "False", ["PublishTrimmed"] = "False", ["PublishProtocol"] = "FileSystem", ["PublishDir"] = @"bin\Release\Test" }; var targetsToBuild = new[] { "Restore", "Rebuild", "Publish" }; var request = new BuildRequestData(path, properties, null, targetsToBuild, null); var parameters = new BuildParameters(new ProjectCollection()); BuildManager.DefaultBuildManager.ResetCaches(); var result = BuildManager.DefaultBuildManager.Build(parameters, request); 但是,我遇到以下异常: The SDK 'Microsoft.NET.Sdk' specified could not be found. 为什么 BuildManager 的行为与 msbuild 不同,有没有办法解决这个问题? 安装后您是否尝试验证您的网络 SDK 并检查了 envo?

回答 1 投票 0

设置 Azure DevOps 构建机器 - 无法解析 SDK“Microsoft.NET.SDK.WorkloadAutoImportPropsLocator”

我正在 Azure DevOps 中设置管道。我决定设立自己的代理人。当我最初尝试构建管道时,它说找不到 C:\Program Files\

回答 1 投票 0

使用 MSBuild 构建 ASP.NET Web 表单应用程序时出现错误 CS0433

我正在开发 ASP.NET Web 窗体应用程序 (.NET Framework 4.7.2),并尝试使用 MSBuild 构建解决方案。 msbuild Project.sln /p:Configuration=Release /p:Platform="Any CPU"

回答 2 投票 0

如何复制项目并将每个项目大写?

在 MSBuild 中,很容易复制属性并将值大写: 莎拉 $(名称.ToUpper()) 在 MSBuild 中,很容易复制属性并将值大写: <PropertyGroup> <Name>Sarah</Name> <UpperName>$(Name.ToUpper())</UpperName> </PropertyGroup> 如何复制项目类型名称的每个项目,将其大写,并创建新的项目类型UpperNames? <ItemGroup> <Names Include="Tim" /> <Names Include="Sam" /> </ItemGroup> 您可以将项目展平为属性,将其大写,然后创建新的项目类型: <Target Name="Target1"> <PropertyGroup> <FlatNames>@(Names)</FlatNames> <FlatNames>$([MSBuild]::Unescape($(FlatNames.ToUpper())))</FlatNames> </PropertyGroup> <ItemGroup> <UpperNames Include="$(FlatNames)" /> </ItemGroup> <Message Text="UpperNames %(UpperNames.Identity)" /> </Target>

回答 1 投票 0

宏 $(VCTargetsPath) 到底定义在哪里?

我们之前有过讨论。 https://social.msdn.microsoft.com/Forums/vstudio/en-US/e04e7791-c0c4-4598-b900-310878f5af45/how-can-i-locate-and-change-the-vctargetspath-variable?forum=微软构建 之后唷...

回答 2 投票 0

如何正确编写批处理文件以供发布在.NET编程过程中添加不同的预编译宏?

我有以下代码: #如果是电脑 var rootPath = Path.Combine("dist"); #别的 var rootPath = Path.Combine(@"/bin/bash"); #万一 我想在

回答 1 投票 0

.pubxml 中的 MsBuild DefineConstants 无法正常工作

我有 ASP.NET Core + Blazor 应用程序(默认模板)和 2 个项目。 当我创建 IIS 发布配置文件时:

回答 0 投票 0

MSBuild - 根据具体情况引入PackageReference

这个想法是,如果 BuildConfigurations 元数据中未指定活动/当前构建配置,则将引用的项目作为包拉取。否则它将被添加为 ProjectReference。在...

回答 1 投票 0

如何在您的家用电脑上成功构建从 GitHub 下载的 Microsoft.Dotnet.Wpf.sln 存储库?

我正在尝试构建一个从 GitHub 下载的 Microsoft.Dotnet.Wpf.sln。我按照说明中所述安装了 Visual Studio 2022 Preview。现在,当我打开 Microsoft.Dotnet.Wpf...

回答 1 投票 0

dotnet 发布配置文件忽略 pubxml 文件

我有以下通过 Visual Studio 2019 创建的 pubxml 文件: <

回答 4 投票 0

当<Compile>和<EmbeddedResource>之外的文件发生更改时,如何避免 Visual Studio 增量构建无法运行?

我有一个 VS2017 csharp 项目,.csproj 文件如下所示: 执行 我有一个 VS2017 csharp 项目,.csproj 文件如下所示: <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.0</TargetFramework> </PropertyGroup> <ItemGroup> <MyItem Include="file.dat" /> </ItemGroup> <PropertyGroup> <PrepareResourcesDependsOn> $(PrepareResourcesDependsOn); MyCompileTarget </PrepareResourcesDependsOn> <CoreCompileDependsOn> $(CoreCompileDependsOn); MyCompileTarget </CoreCompileDependsOn> </PropertyGroup> <Target Name="MyCompileTarget" Inputs="@(MyItem)" Outputs="@(MyItem->'%(FileName).out')"> ... </Target> </Project> 其中 MyCompileTarget 是从 file.out 生成 file.dat 的目标(在实际代码中,增量构建目标和属性位于通过 NuGet 包自动包含的目标文件中)。 问题是,如果我更改 file.dat 并按 Build,则根本不会执行 目标(但 MyTarget 使用 Rebuild 或使用 msbuild 运行时可以正确执行)。我希望执行 MyCompileTarget 以便更新 file.out 文件。 如果我使用 BeforeBuild 或 AfterBuild 而不是 PrepareResourcesDependsOn 等,也会出现同样的问题 除非 @(Compile) 或 @(EmbeddedResource) 中的某些文件发生更改,否则 Visual Studio 增量构建似乎不会启动。事实上,如果我添加以下内容 <EmbeddedResource>file.dat</EmbeddedResource> 增量构建按预期工作(但显然我不想将 file.dat 嵌入到生成的程序集中)。 如果修改了file.dat,并且相应的生成文件早于file.dat或不存在,是否可以强制Visual Studio启用增量构建? 注意:使用 VS2015、.NET CORE 或 .NET FRAMEWORK 也会出现同样的问题。 另外,如果我更改 csharp 文件,将触发增量构建,因此它将触发 MyTask,但前提是 file.dat 比生成的文件更新(如预期)。 提前致谢, 法比奥。 如果 file.dat 被修改,是否可以强制 Visual Studio 启用增量构建 您可以在项目文件中将属性 DisableFastUpToDateCheck 设置为 true,以禁用 Visual Studio 构建管理器的 FastUpToDateCheck: <PropertyGroup> <DisableFastUpToDateCheck>True</DisableFastUpToDateCheck> </PropertyGroup> 检查MSDN有关DisableFastUpToDateCheck的信息: 仅适用于 Visual Studio 的布尔值。 视觉工作室 构建管理器使用名为 FastUpToDateCheck 的过程来确定 是否必须重建项目才能保持最新状态。 此过程是 比使用 MSBuild 更快地确定这一点。 设置 将 DisableFastUpToDateCheck 属性设置为 true 可让您绕过 Visual Studio 构建管理器并强制它使用 MSBuild 来确定是否 该项目是最新的 更新: 此外,我们还可以将 UpToDateCheckInput 设置为项目: <UpToDateCheckInput Include="file.dat" /> 禁用 VS 快速更新检查会让你的构建速度变慢。别这样做! 相反,请确保最新检查了解项目中的项目以及它们与构建的关系。为此,您可以将两种项目添加到您的项目中: UpToDateCheckInput 用于输入 UpToDateCheckBuilt 用于输出 在您的情况下,您需要第二个选项,因为既有输入又有输出。您需要确保如果删除输出,它会被重建。 <ItemGroup> <UpToDateCheckBuilt Original="@(MyItem)" Include="@(MyItem->'%(FileName).out')"> </ItemGroup> 有关更多信息,请参阅文档: https://github.com/dotnet/project-system/blob/main/docs/up-to-date-check.md

回答 2 投票 0

© www.soinside.com 2019 - 2024. All rights reserved.