以太坊im钱包下载地址|csproj编译
理解C#项目构建配置文件——MSBuild csproj文件 - 知乎
理解C#项目构建配置文件——MSBuild csproj文件 - 知乎首发于FreewheelLee的编程艺术切换模式写文章登录/注册理解C#项目构建配置文件——MSBuild csproj文件FreewheelLeeMicrosoft 全栈工程师内容概要什么是 csproj 文件和MSBuildcsproj 文件的主要构成元素C#项目构建过程 ( csproj 文件的解析过程 )小结和提示(MSBuild 涉及的内容非常多,同时官方文档也很齐全,本文不会一一细聊。本文的目的在于简要地描述整个MSBuild csproj 解析和执行的大概轮廓,指出一些 关键点,方便读者进一步深入学习。)什么是 MSBuild和csproj 文件 (MSBuild - MSBuild)The Microsoft Build Engine is a platform for building applications. This engine, which is also known as MSBuild, provides an XML schema for a project file that controls how the build platform processes and builds software. 简单的说 MSBuild 是一个构建应用程序的平台和工具,本文特指构建 C# 应用程序。MSBuild 使用 XML 格式的配置文件控制如何构建应用程序。MSBuild 跟 Visual Studio 是什么关系?Visual Studio uses MSBuild, but MSBuild doesn't depend on Visual Studio. By invoking msbuild.exe on your project or solution file, you can orchestrate and build products in environments where Visual Studio isn't installed.Visual Studio uses MSBuild to load and build managed projects. The project files in Visual Studio (.csproj, .vbproj, .vcxproj, and others) contain MSBuild XML code that executes when you build a project by using the IDE. Visual Studio projects import all the necessary settings and build processes to do typical development work, but you can extend or modify them from within Visual Studio or by using an XML editor.即 MSBuild 是一个独立的工具,Visual Studio 使用 MSBuid 加载和构建项目。当 Visual Studio 新建一个 C# 项目时,会在project folder(而不是 solution folder)下新建一个 csproj 文件,MSBuild 通过解析这个文件就知道如何构建当前的程序。看个简单的 csproj 文件例子 —— 一个非常简单的 XML 文件
这就是 用 Visual Studio 新建的 Console Application project 的 csproj 文件,是不是非常简洁?甚至完全看不出这样一个简短的文件如何让 MSBuild 知道怎么构建这个项目。揭晓这个答案之前,先熟悉一下 csproj 文件的主要构成元素之后文章的内容都会使用 https://github.com/freewheel70/MSBuildSample 作为例子,读者可以自行 clone 下来操作。csproj 文件的主要构成元素为避免歧义,所有元素名我都保留了英文(如 Project元素)而斜体英文名不是元素名而是指代一类元素的种类名称如(如 Property 元素)Project 元素这是根元素,其中最重要的属性(元数据)之一就是上面看到的 Sdk ,稍后详解PropertyGroup 元素 和 Property 元素 (MSBuild Properties - MSBuild)顾名思义PropertyGroup 元素是一个 group 元素,子元素是一些 property 元素。而 property 元素是简单的键值对,即元素名为键,元素内容为值 (元素名字不是 Property)。例如,上面那个例子里的 PropertyGroup 里包含了OutputType, TargetFramework, ImplicitUsing 等 Property我们也可以自定义, 比如 新增一个 PropertyGroup
换句话说,你可以理解为 property 就是一些自定义变量。在构建的过程中可以利用这些变量值,比如作为判断语句的条件值,作为某个任务的输入,等等。重复定义了Property 会发生什么?如果后面的 Property 名字跟之前的相同,那么后面的值会覆盖前面的值。例如:
... ...
那么在实际运行时, MyName 的值是 FreeLee2ItemGroup元素和Item元素 (MSBuild Items - MSBuild)顾名思义ItemGroup元素是一个 group 元素,子元素是一些 Item 元素Item 元素: 在 MSBuild 中,Item 是对一个或多个文件的引用, 包含元数据(如文件名、路径和版本号)一些常见的 Item 元素以及它们支持的元数据可以参考 Common MSBuild Project Items - MSBuild 和 更详细的内容参考https://github.com/dotnet/msbuild/blob/main/src/MSBuild/MSBuild/Microsoft.Build.CommonTypes.xsd 示例:
支持通配符
这段 xml 的意思是: 希望MSBuild每次构建总是将 mydata.json 复制到构建输出的文件夹里。效果如下图注意:Item 元素本身并不会要求MSBuild做任何操作,它只是非常纯粹的文件引用,CopyToOutputDirectory也只是一个元数据而不是动作。真正引导 MSBuild 构建的是后面马上会讲解的 Task。重复定义了Item 会发生什么?不同于 Property, 重复的 Item 不会相互覆盖,而是变成一个列表比如
那么 引用 Compile Item 时,就会获得一个包含了 file2.cs 和 file1.cs 的列表。 Target 元素和 Task 元素 (MSBuild Targets - MSBuild ,MSBuild Tasks - MSBuild)Target和Task MSBuild构建过程中最核心最重要的元素。Target 是一系列任务的组合(所以理解为 TaskGroup 也没毛病),Task 则是具体的任务 —— 比如,复制文件,输出信息,编译源码,构建引用的其他项目。Target 最重要的属性是AfterTargets, BeforeTargets 和 DependsOnTargets ,看名字就知道它们都是关于执行顺序的。Task 元素种类很多,最简单的就是 Message ,它做的事情就是在 console 上输出一段信息,比如 hello world 示例:
上面这个自定义名为 MyTarget 的 Target 会在 CoreCompile 后执行,执行时输出三段文本上面的 $(OS) $(PROCESSOR_ARCHITECTURE) 引用了环境变量,我们也可以使用 $(MyName) 来引用我们上面自定义的 Property更多常用的Task可以参考 MSBuild Task Reference - MSBuild 例如重复定义了Target会发生什么?跟 property 类似,重复定义的 Target 会覆盖之前的定义,例如
... ...
实际运行输出的是 Hello World 介绍完主要的元素后,开始正式理解 MSBuild project file 的解析和执行过程。正如文章开头的那个例子,一个非常简单的MSBuild Project file 里明明没有定义任何的 Target 和 task,为什么却能让 MSBuild 成功构建这个项目呢?答案就是 Project 元素的 Sdk 属性MSBuild 根据 Sdk 属性的值,会隐式地导入一些常见的 Properties 和 Targets 然后生成一个新的完整的详细的 MSBuild Project file (可以这么理解,虽然并不会真的生成一个文件)具体的生成逻辑是先导入sdk定义的常见的 properties再复制 MSBuild project file 的主体内容 最后导入sdk定义的常见的 targets对这个顺序的理解很重要,因为如果在 MSBuild project file 定义的 property 与sdk定义的常见的 property 重名,我们定义的值会成功覆盖默认值。如果在 MSBuild project file 定义的 targets与sdk定义的常见的 targets重名,我们定义的targets会被覆盖而不生效。这些常见的 Properties 和 Targets 的内容可以查看 sdk/src/Tasks/Microsoft.NET.Build.Tasks/sdk at main · dotnet/sdk 或者在本地文件夹 C:\Program Files\dotnet\sdk\6.0.202\Sdks\Microsoft.NET.Sdk\Sdk\ 下(根据安装的 sdk 版本不同可能路径不同)其中的导入逻辑相对复杂,这边不做展开。我们可以使用MSBuild CLI的一个参数 preprocess 生成完整的 MSBuild project file 方便我们理解,例如在我的示范项目下运行 (运行报错的读者可以看看文章结尾的小提示)msbuild -preprocess:.\MSBuildSample\Complete.csproj .\MSBuildSample\MSBuildSample.csproj就会得到一个Complete.csproj文件,打开这个文件,可以看到一些有意思的东西。首先是这个文件特别大,16000+行,但是其中有大量的注释,这些注释对理解这个生成过程非常有帮助,例如清晰地指出从什么地方导入了这些内容。通过搜索也可以验证上面说的3个步骤的顺序 —— 如,我们编写的MSBuild Project file 的内容被放在了中间。扩展点在 Complete.csproj 中搜索 AfterCompile注释中清楚地写着,如果你想在 Compile 结束后做点什么,可以重新定义 AfterCompile 这个target。即 AfterCompile 可以看作一个扩展点。怎么做呢? 在 MSBuildSample.csproj 里重新定义吗?读者可以试试,会发现不起作用。原因就是上面提到的2个点:1. MSBuildSample.csproj 的内容在最终的 Complete.csproj 中处于中间, 而 上面截图中的代码处于后面 2. 重复定义的 Target 会由后面覆盖前面,因此 在 MSBuildSample.csproj 里定义 AfterCompile target 会被覆盖正确的方式之一是新建一个 Directory.Build.targets 文件,然后在里面重新定义 AfterCompile target参考 https://github.com/freewheel70/MSBuildSample/blob/main/MSBuildSample/Directory.Build.targets 为什么是 Directory.Build.targets 呢? 因为 Directory.Build.targets 文件会在较后面才导入 —— 读者可以在 Complete.csproj 里验证。除了 AfterCompile,读者可以在 Complete.csproj 里查找其他的 扩展点target。小结Project, PropertyGroup, Property, ItemGroup, Item, Target, Task 是 MSBuild Project file 中最重要最常见的元素Project 的 sdk 属性会让 MSBuild 隐式地导入一些常见的 properties 和 targets通过新建一个 Directory.Build.targets 文件,定义所需要的 target 或者重新定义扩展点 target 可以引导 MSBuild 构建,执行我们需要的任务小提示msbuild 指令需要在 visual studio 的 terminal 下运行,在外部的 terminal 会报错 visual studio 里可以调整 MSBuild 输出日志的详细程度,方便学习进阶主题有兴趣进阶学习的读者可以考虑下面几个主题使用 Visual Studio 和 MSBuild.exe 构建有什么区别Item definitions —— 怎么自定义 Item Task 的输入和输出UsingTask 元素 —— 怎么自定义 TaskTargets 执行顺序 (Target Build Order - MSBuild) Parallel execution —— 并行执行其他 参考链接(或有趣的相关链接):How MSBuild builds projects - MSBuild MSBuild Tasks - MSBuild MSBuild Command-Line Reference - MSBuild https://github.com/dotnet/msbuild/tree/main/src/Tasks How can I get MSBuild to copy all files marked as Content to a folder, preserving folder structure? sdk/src/Tasks/Microsoft.NET.Build.Tasks/targets at main · dotnet/sdk https://github.com/dotnet/msbuild/blob/main/src/MSBuild/MSBuild/Microsoft.Build.CommonTypes.xsd 编辑于 2022-05-08 18:14C#msbuild.NET赞同 391 条评论分享喜欢收藏申请转载文章被以下专栏收录FreewheelLee的编程艺术微软全栈工程师,不定期分享各类技术和
理解 C# 项目 csproj 文件格式的本质和编译流程 - walterlv - 博客园
理解 C# 项目 csproj 文件格式的本质和编译流程 - walterlv - 博客园
会员
周边
新闻
博问
AI培训
云市场
所有博客
当前博客
我的博客
我的园子
账号设置
简洁模式 ...
退出登录
注册
登录
walterlv
博客园
首页
新随笔
联系
订阅
管理
理解 C# 项目 csproj 文件格式的本质和编译流程
写了这么多个 C# 项目,是否对项目文件 csproj 有一些了解呢?Visual Studio 是怎么让 csproj 中的内容正确显示出来的呢?更深入的,我能够自己扩展 csproj 的功能吗?
本文将直接从 csproj 文件格式的本质来看以上这些问题。
阅读本文,你将:
可以通读 csproj 文件,并说出其中每一行的含义
可以手工修改 csproj 文件,以实现你希望达到的高级功能(更高级的,可以开始写个工具自动完成这样的工作了)
理解新旧 csproj 文件的差异,不至于写工具解析和修改 csproj 文件的时候出现不兼容的错误
csproj 里面是什么?
总览 csproj 文件
相信你一定见过传统的 csproj 文件格式。就算你几乎从来没主动去看过里面的内容,在版本管理工具中解冲突时也在里面修改过内容。
不管你是新手还是老手,一定都会觉得这么长这么复杂的文件一定不是给人类阅读的。你说的是对的!传统 csproj 文件中有大量的重复或者相似内容,只为 msbuild 和 Visual Studio 能够识别整个项目的属性和结构,以便正确编译项目。
不过,既然这篇文章的目标是理解 csproj 文件格式的本质,那我当然不会把这么复杂的文件内容直接给你去阅读。
我已经将整个文件结构进行了极度简化,然后用思维导图进行了分割。总结成了下图,如果先不关注文件的细节,是不是更容易看懂了呢?
如果你此前也阅读过我的其他博客,会发现我一直在试图推荐使用新的 csproj 格式:
将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件
让一个 csproj 项目指定多个开发框架
那么新格式和旧格式究竟有哪些不同使得新的格式如此简洁?
于是,我将新的 csproj 文件结构也进行简化,用思维导图进行了分割。总结成了下图:
比较两个思维导图之后,是不是发现其实两者本是相同的格式。如果忽略我在文字颜色上做的标记,其实两者的差异几乎只在文件开头是否有一个 xml 文件标记()。我在文字颜色上的标记代表着这部分的部件是否是可选的,白色代表必须,灰色代表可选;而更接近背景色的灰色代表一般情况下都是不需要的。
我把两个思维导图放到一起方便比较:
会发现,传统格式中 xml 声明、Project 节点、Import (props)、PropertyGroup、ItemGroup、Import (targets) 都是必要的,而新格式中只有 Project 节点 和 PropertyGroup 是必要的。
是什么导致了这样的差异?在了解 csproj 文件中各个部件的作用之前,这似乎很难回答。
了解 csproj 中的各个部件的作用
xml 声明部分完全没有在此解释的必要了,为兼容性提供了方便,详见:XML - Wikipedia。
接下来,我们不会依照部件出现的顺序安排描述的顺序,而是按照关注程度排序。
PropertyGroup
PropertyGroup 是用来存放属性的地方,这与它的名字非常契合。那么里面放什么属性呢?答案是——什么都能放!
在这里写属性就像在代码中定义属性或变量一样,只要写了,就会生成一个指定名称的属性。
比如,我们写:
那么,就会生成一个 Foo 属性,值为字符串 walterlv is a 逗比。至于这个属性有什么用,那就不归这里管了。
这些属性的含义完全是由外部来决定的,例如在旧的 csproj 格式中,编译过程中会使用 TargetFrameworkVersion 属性,以确定编译应该使用的 .NET Framework 目标框架的版本(是 v4.5 还是 v4.7)。在新的 csproj 格式中,编译过程会使用 TargetFrameworks 属性来决定编译应该使用的目标框架(是 net47 还是 netstandard2.0)。具体是编译过程中的哪个环节哪个组件使用了此属性,我们后面会说。
从这个角度来说,如果你没有任何地方用到了你定义的属性,那为什么还要定义它呢?是的——这只是浪费。
PropertyGroup 可以定义很多个,里面都可以同等地放属性。至于为什么会定义多个,原因无外乎两个:
为了可读性——将一组相关的属性放在一起,便于阅读和理解意图(旧的 csproj 谈不上什么可读性)
为了加条件——有的属性在 Debug 和 Release 下不一样(例如条件编译符 DefineConstants)
额外说一下,Debug 和 Release 这两个值其实是在某处一个名为 Configuration 的属性定义的,它们其实只是普通的字符串而已,没什么特殊的意义,只是有很多的 PropertyGroup 加上了 Debug Release 的判断条件才使得不同的 Configuration 具有不同的其他属性,最终表现为编译后的巨大差异。由于 Configuration 属性可以放任意字符串,所以甚至可以定义一个非 Debug 和 Release 的配置(例如用于性能专项测试)也是可以的。
ItemGroup
ItemGroup 是用来指定集合的地方,这与它的名字非常契合。那么这集合里面放什么项呢?答案是——什么都能放!
是不是觉得这句话跟前面的 PropertyGroup 句式一模一样?是的——就是一模一样!csproj 中的两个大头都这样不带语义,几乎可以说明 csproj 文件是不包含语义的,它能够用来做什么事情纯属由其他模块来指定;这为 csproj 文件强大的扩展性提供了格式基础。
既然什么都能放,那我们放这些吧:
于是我们就有 4 个类型为 Foo 的项了,至于这 4 个 Foo 项有什么作用,那就不归这里管了。
这些项的含义与 PropertyGroup 一样也是由外部来决定。具体是哪个外部,我们稍后会说。但是我们依然有一些常见的项可以先介绍介绍:
Reference 引用某个程序集
PackageReference 引用某个 NuGet 包
ProjectReference 引用某个项目
Compile 常规的 C# 编译
None 没啥特别的编译选项,就为了执行一些通用的操作(或者是只是为了在 Visual Studio 列表中能够有一个显示)
Folder 一个空的文件夹,也没啥用(不过标了这个文件夹,Visual Studio 中就能有一个文件夹的显式,即便实际上这个文件夹可能不存在)
ItemGroup 也可以放很多组,一样是为了提升可读性或者增加条件。
Import
你应该注意到在前面的思维导图中,无论是新 csproj 还是旧 csproj 文件,我都写了两个 Import 节点。其实它们本质上是完全一样的,只不过在含义上有不同。前面我们了解到 csproj 文件致力于脱离语义,所以分开两个地方写几乎只是为了可读性考虑。
那么前面那个 Import 和后面的 Import 在含义上有何区别?思维导图的括号中我已说明了含义。前面是为了导入属性(props),后面是为了导入 Targets。属性就是前面 PropertyGroup 中说的那些属性和 ItemGroup 里说的那些项;而 Targets 是新东西,这才是真正用来定义编译流程的关键,由于 Targets 是所有节点里面最复杂的部分,所以我们放到最后再说。
那么,被我们 Import 进来的那些文件是什么呢?用两种扩展名,定义属性的那一种是 .props,定义行为的那一种是 .targets。
这两种文件除了含义不同以外,内容的格式都是完全一样的——而且——就是 csproj 文件的那种格式!没错,也包含 Project、Import、PropertyGroup、ItemGroup、Targets。只不过,相比于对完整性有要求的 csproj 文件来说,这里可以省略更多的节点。由于有 Import 的存在,所以一层一层地嵌套 props 或者 targets 都是可能的。
说了这么多,让我们来看其中两个 .props 文件吧。
先看看旧格式 csproj 文件中第一行一定会 Import 的那个 Microsoft.Common.props。
文件太长,做了大量删减,但也可以看到文件格式与 csproj 几乎是一样的。此文件中,根据其他属性的值有条件地定义了另一些属性。
再看看另一个 MSTest 单元测试项目中被隐式 Import 进 csproj 文件中的 .props 文件。(所谓隐式地 Import,只不过是被间接地引入,在 csproj 文件中看不到这个文件名而已。至于如何间接引入,因为涉及到 Targets,所以后面一起说明。)
Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.dll
Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.dll
Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.dll
此文件中将三个 dll 文件从 MSTest 的 NuGet 包中以链接的形式包含到项目中,并且此文件在 Visual Studio 的解决方案列表中不可见。
可以看出,引入的 props 文件可以实现几乎与 csproj 文件中一样的功能。
那么,既然 csproj 文件中可以完全实现这样的功能,为何还要单独用 props 文件来存放呢?原因显而易见了——为了在多个项目中使用,一处更新,到处生效。所以有没有觉得很好玩——如果把版本号单独放到 props 文件中,就能做到一处更新版本号,到处更新版本号啦!
Target
终于开始说 Target 了。为什么会这么期待呢?因为前面埋下的各种伏笔几乎都要在这一节点得到解释了。
一般来说,Target 节点写在 csproj 文件的末尾,但这个并不是强制的。Targets 是一种非常强大的功能扩展方式,支持 msbuild 预定义的一些指令,支持命令行,甚至支持使用 C# 直接编写(当然编译成 dll 会更方便些),还支持这些的排列组合和顺序安排。而我们实质上的编译过程便全部由这些 Targets 来完成。我们甚至可以直接说——编译过程就是靠这些 Target 的组合来完成的。
如果你希望全面了解 Targets,推荐直接阅读微软的官方文档 MSBuild Targets,而本文只会对其进行一些简单的概述。当然如果你非常感兴趣,还可以阅读我另外几篇关于 Target 使用相关的文章:
如何创建一个基于命令行工具的跨平台的 NuGet 工具包 - 吕毅
如何创建一个基于 MSBuild Task 的跨平台的 NuGet 工具包 - 吕毅
每次都要重新编译?太慢!让跨平台的 MSBuild/dotnet build 的 Target 支持差量编译 - 吕毅
如何最快速地将旧的 NuGet 包 (2.x, packages.config) 升级成新的 NuGet 包 (4.x, PackageReference) - 吕毅
不过,为了简单地理解 Target,我依然需要借用官方文档的例子作为开头。
这份代码定义了一个名为 Construct 的 Target,这是随意取的一个名字,并不重要——但是编译过程中会执行这个 Target。在这个 Target 内部,使用了一个 msbuild 自带的名为 Csc 的 Task。这里我们再次引入了一个新的概念 Task。而 Task 是 Target 内部真正完成逻辑性任务的核心;或者说 Target 其实只是一种容器,本身并不包含编译逻辑,但它的内部可以存放 Task 来实现编译逻辑。一个 Target 内可以放多个 Task,不止如此,还能放 PropertyGroup 和 ItemGroup,不过这是仅在编译期生效的属性和项了。
@(Compile) 是 ItemGroup 中所有 Compile 类型节点的集合。还记得我们在 ItemGroup 小节时说到每一种 Item 的含义由外部定义吗?是的,就是在这里定义的!本身并没有什么含义,但它们作为参数传入到了具体的 Task 之后便有了此 Task 指定的含义。
于是
如果后面定义了一个跟此名称一样的 Target,那么后一个 Target 就会覆盖前一个 Target,导致前一个 Target 失效。
再次回到传统的 csproj 文件上来,每一个传统格式的 csproj 都有这样一行:
而引入的这份 .targets 文件便包含了 msbuild 定义的各种核心编译任务。只要引入了这个 .targets 文件,便能使用 msbuild 自带的编译任务完成绝大多数项目的编译。你可以自己去查看此文件中的内容,相信有以上 Target 的简单介绍,应该能大致理解其完成编译的流程。这是我的地址:C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Microsoft.CSharp.targets。
Project
所有的 csproj 文件都是以 Project 节点为根节点。既然是根节点为何我会在最后才说 Project 呢?因为这可是一个大悬念啊!本文一开始就描述了新旧两款 csproj 文件格式的差异,你也能从我的多篇博客中感受到新格式带来的各种好处;而简洁便是新格式中最大的好处之一。它是怎么做到简洁的呢?
就靠 Project 节点了。
注意到新格式中 Project 节点有 Sdk 属性吗?因为有此属性的存在,csproj 文件才能如此简洁。因为——所谓 Sdk,其实是一大波 .targets 文件的集合。它帮我们导入了公共的属性、公共的编译任务,还帮我们自动将项目文件夹下所有的 **\*.cs 文件都作为 ItemGroup 的项引入进来。
如果你希望看看 Microsoft.NET.Sdk 都引入了哪些文件,可以去本机安装的 msbuild 或 dotnet 的目录下查看。当我使用 msbuild 编译时,我的地址:C:\Program Files\dotnet\sdk\2.1.200\Sdks\Microsoft.NET.Sdk\build\。比如你可以从此文件夹里的 Microsoft.NET.GenerateAssemblyInfo.targets 文件中发现 AssemblyInfo.cs 文件是如何自动生成及生效的。
编译器是如何将这些零散的部件组织起来的?
这里说的编译器几乎只指 msbuild 和 Roslyn,前者基于 .NET Framework,后者基于 .NET Core。不过,它们在处理我们的项目文件时的行为大多是一致的——至少对于通常项目来说如此。
我们前一部分介绍每个部件的时候,已经简单说了其组织方式,这里我们进行一个回顾和总结。
当 Visual Studio 打开项目时,它会解析里面所有的 Import 节点,确认应该引入的 .props 和 .targets 文件都引入了。随后根据 PropertyGroup 里面设置的属性正确显示属性面板中的状态,根据 ItemGroup 中的项正确显示解决方案管理器中的引用列表、文件列表。——这只是 Visual Studio 做的事情。
在编译时,msbuild 或 Roslyn 还会重新做一遍上面的事情——毕竟这两个才是真正的编译器,可不是 Visual Studio 的一部分啊。随后,执行编译过程。它们会按照 Target 指定的先后顺序来安排不同 Target 的执行,当执行完所有的 Target,便完成了编译过程。
新旧 csproj 在编译过程上有什么差异?
相信读完前面两个部分之后,你应该已经了解到在格式本身上,新旧格式之间其实并没有什么差异。或者更严格来说,差异只有一条——新格式在 Project 上指定了 Sdk。真正造成新旧格式在行为上的差别来源于默认为我们项目 Import 进来的那些 .props 和 .targets 不同。新格式通过 Microsoft.NET.Sdk 为我们导入了更现代化的 .props 和 .targets,而旧格式需要考虑到兼容性压力,只能引入旧的那些 .targets。
新的 Microsoft.NET.Sdk 以不兼容的方式支持了各种新属性,例如新的 TargetFrameworks 代替旧的 TargetFrameworkVersion,使得我们的 C# 项目可以脱离 .NET Framework,引入其他各种各样的目标框架,例如 netstandard2.0、net472、uap10.0 等(可以参考 从以前的项目格式迁移到 VS2017 新项目格式 - 林德熙)了解可以使用那些目标框架。
新的 Microsoft.NET.Sdk 以不兼容的方式原生支持了 NuGet 包管理。也就是说我们可以在不修改 csproj 的情况之下通过 NuGet 包来扩展 csproj 的功能。而旧的格式需要在 csproj 文件的末尾添加如下代码才可以获得其中一个 NuGet 包功能的支持:
不过好在 NuGet 4.x 以上版本在安装 NuGet 包时自动为我们在 csproj 中插入了以上代码。
更多资料
如果你在阅读本文时还有更多问题,可以阅读我和朋友的其他相关博客,也可以随时在下方向我留言。如果没有特别原因,我都是在一天之内进行回复。
项目文件中的已知属性(知道了这些,就不会随便在 csproj 中写死常量了) - 吕毅
让一个 csproj 项目指定多个开发框架 - 吕毅
从以前的项目格式迁移到 VS2017 新项目格式 - 林德熙
将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件 - 吕毅
自动将 NuGet 包的引用方式从 packages.config 升级为 PackageReference - 吕毅
posted @
2018-05-19 07:58
walterlv
阅读(9601)
评论(1)
编辑
收藏
举报
会员力量,点亮园子希望
刷新页面返回顶部
公告
Copyright © 2024 walterlv
Powered by .NET 8.0 on Kubernetes
© 2014-2018 walterlv, all rights reserved.
Designed by: walterlv
使用微软的MSBuild.exe编译VS .sln .csproj 文件 - jack_Meng - 博客园
使用微软的MSBuild.exe编译VS .sln .csproj 文件 - jack_Meng - 博客园
会员
周边
新闻
博问
AI培训
云市场
所有博客
当前博客
我的博客
我的园子
账号设置
简洁模式 ...
退出登录
注册
登录
Jack_孟
使用微软的MSBuild.exe编译VS .sln .csproj 文件
msbuild官方参考文档
MSBuild 命令行参考
=======================================================================================
如何用msbuid编译项目
msbuid编译我们用vs写好代码以后,用vs编译一下就生成相应的bin文件 ,但有时项目比较大,每次都要重新打开vs加载很浪费时间 ,
我们这里采用直接调用vs自带的msbuild的方式来编译。这样就不用每次都开启vs了。
用vs自带的命令调用msbuild
用msbuild编译一种方式时用vs 自带命令打开。 在vs的命令提示下,输入
msbuild ***.sln /p:Configuration=Debug
默认采用的就是debug build ,所以 /p:Configuration=Debug 可以不加
如果想编译成Release
改成
msbuild ***.sln /p:Configuration=Release
添加环境变量直接cmd编译
在计算机属性-》属性-》高级系统设置 =》环境变量=》找到path=》在后面添加msbuid路径
;C:\Program Files (x86)\MSBuild\12.0\Bin
我这里采用的是vs2013中的msbuid
vs2017msbuild所在位置 是
;C:\Program Files (x86)\MSBuild\15.0\Bin
vs2015是14,msbuild版本不一样。
;C:\Program Files (x86)\MSBuild\14.0\Bin
添加完环境变量以后,就可以直接在cmd下编译了。 到项目文件夹下面,按shift+右键 , 从此处打开命令窗口。 输入
msbuild consold1.sln
之后到bin目录 下查看,发现已经有debug文件夹生成
相应的,如果采用/p:Configuration=Release 会有相应的release文件生成。
直接用批处理来编译,不用每次输入了
把以下文件写入bat文件中,以后直接执行就可以了。
msbuild console1.sln /p:Configuration=Release
如果要指定输出目录的话,加上outputpath ,中间用;号进行连
msbuild /p:Configuraton=release;outputpath=e:\temp12333
如果编译指定的项目 可以用如下命令
msbuild c2/c2.csproj /p:Configuration=Release;outputpath=E:\project\demo\console1\c2Release
出处:http://www.hechunbo.com/index.php/archives/199.html
=======================================================================================
命令行调用MSBuild编译项目时指定参数
为了方便打包测试,自己PowerShell写了一个编译和发布的脚本,调用msbuild通过命令行来编译当前解决方案
后来发现一个问题,用VS编译解决方案,我通过 项目属性-Build设置 Release和x86
但是脚本直接调用MSBuild编译,有一个项目的属性死活就是Release和Any Cpu
后来看MSBuild的参数,有一个是可以指定的这两个属性的,就是 /property 缩写 /p
MSBuild添加下面的参数
/p:Configuration=Release;Platform=x86
后续:今天又遇到了VS可以正常编译,但是用msbuild不行的问题
后来发现可以指定target来对应编译方式
/target:Clean;Rebuild
出处:https://www.cnblogs.com/wormday/p/7020467.html
=======================================================================================
msbuild命令编译项目文件的参数
最近研究使用发布机发布项目,固然需要使用命令行来编译项目文件,此次的编译使用的是msbuild,也是当下官方推荐;当然还有devenv; 另外说明:本次的实验使用的为Visual Studio 2017 ##相关参考
MSDN : MSBuild使用及一些说明
##指令目录说明 在vs2017之前,msbuild都是跟随.net framework一起发布,在vs2017后需要兼容.net core的编译,所以与vs打包整合了,如果用的是visual studio 2017或者使用了c# 5.0中的新特性,建议使用msbuild V15.0的版本来编译;V15.0的目录也是在visual studio的安装目录下有单独的msbuild目录。 ##指令语法 ###指令的使用语法 MSBuild.exe [选项] [项目文件 | 目录] ###常用开关
开关开关缩写描述示例
/target:
/t:
在此项目中生成这些目标。使用分号或逗号分隔多个目标,或者分别指定每个目标。
/target:Resources;Compile
/property:< n >=< v >
/p:
设置或重写这些项目级属性。< n > 是属性名,< v > 为属性值。请使用分号或逗号分隔多个属性,或者分别指定每个属性。
/property:WarningLevel=2;OutDir=bin\Debug\
/toolsversion:< version >
/tv
要在生成过程中使用的 MSBuild 工具集(任务、目标等)的版本。此版本将重写个别项目指定的版本
/toolsversion:3.5
的以上常用的指令中用的最多的为前两个 /target:和/property:,target用来指定生成项目的目标等;而/property则是一相相当重要的开关属性了下面来特别说明它是如何重要的。 ###开关讲解
/Property:< n >= < v >
首先来看我们的项目文件.csproj文件中的一个片段
示例中我们可以看到有请多的宏定义$(MSBuildBinPath)、$(VSToolsPath)等,而这些宏是可以使用/property来进行定义的;也就是说.csproj文件中的宏都可以使用/property来进行定义;下面来看一个例子: 命令如下:
msbuild d:\Projects\Web\Web.csproj /t:ResolveReferences;Compile /t:_WPPCopyWebApplication /p:Configuration=Release /p:WebProjectOutputDir=d:\website 在项目中使用了生成事件,copy了一个文件;使用了$(SolutionDir)的宏指令 执行后的错误提示: 解决办法: 添加 /p 开关如下 :/p:SolutionDir=‘指定的路经’ 这样问题就解决了
扩展问题:如果自定义一些宏了,可以使用/property来定义吗? ##结语 好了,先写这么多,很久没有写blog了,感觉写出来有头没尾,草草的结个尾
出处:https://blog.csdn.net/bklydxz/article/details/77933222
=======================================================================================
=======================================================================================
最近在看一些算法和测试一些程序,以及帮团队测试程序,团队使用了vs开发环境创建的sln项目文件,我使用的是公司的机器,没有任何权限安装程序等操作,但是又需要编译一些程序,所以我想到了,使用MSBuild.exe进行编译。
如果你的机器上没有装有VisualStudio,那么可以使用MSBuild来build .sln或project。可以不用安装vs程序,MSBuild可以通过安装.NETFramework来安装,一般的安装路径为C:\Windows\Microsoft.NET\Framework。其实devenv执行build时候,后台也是调用MSBuild来build的。
可以使用msbuild /?来查看详细的帮助;
今天就简单的介绍下使用MSBuild.exe编译程序的方法:
确认你使用的vs的版本,这个可以从sln文件中看到,不会看的可以查百度
确认你本机已经安装了那个版本的MSBuild.exe程序,具体的可以使用dir查看,如:C:\>dir /s /b /d MSBuild.exe 可以查看本机各个版本。
使用对应版本的MSBuild.exe编译sln文件,例如编译vs2015编写的程序:
%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe "c:\test\test1.sln" /property:Configuration=Debug /t:build /p:VisualStudioVersion=14.0
说明:如果你想编译单个文件,或者是测试某段程序算法等,可以不用考虑使用那个版本的MSBuild.exe程序。
简单实例:
MSBuild MyApp.sln /t:Rebuild /p:Configuration=Release
MSBuild MyApp.csproj /t:Clean /p:Configuration=Debug;/p:Platform=x86;TargetFrameworkVersion=v3.5
同样注意,如果project引用了其他的projects的时候,最好build整个.sln。
参考: MSBuild入门 MSBuild入门(续) MSBuild功能介绍
=======================================================================================
参考如下:
背景:VS很好很强大,但太费系统资源了,尤其是在虚拟机在里面装VS的时候更是如此。有时用vi编辑了源代码后,不想开VS IDE编译,但每次打开VS命令行,再切换到工程所在目录,然后手动敲命令太麻烦了。于是产生了集成集成VS命令行编译到.sln文件右键菜单的想法。
直接上图:
本版本支持 Win10 + VS2015
*******************************************************************
*
* 小工具:不用打开项目,右键直接编译*.sln,*.csproj,绿色环保
*
*******************************************************************
需要三步:
1 必需copy本目录到C:\
2 运行Install.reg。(反安装运行Unstall.reg)
3 右键*.sln 或 *.csproj 文件会有相应编译菜单出现。
下载: VSBuild(Win10-VS2015).zip
出处:http://www.cnblogs.com/crazybird/p/5103906.html
=======================================================================================
个人使用
临时手写了个,可以参考吧,把以下内容保存到MSBuildSln.bat
@ECHO OFF
set ms="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe"
cls
%ms% /version
color 0c
ECHO.
ECHO.
echo Do you use this version of MSBuild.exe to compile the current program? Close this window if you don't compile.
pause
color
GOTO End
IF /I "%1"=="Debug" GOTO BuildDebug
IF /I "%1"=="Release" GOTO BuildRelease
IF /I "%1"=="All" GOTO BuildAll
IF /I "%1"=="Minimal" GOTO BuildMinimal
:ER
ECHO.
ECHO Raspkate Command-Line Build Tool v1.0
ECHO.
ECHO Usage:
ECHO build.bat Debug
ECHO Builds the Raspkate with Debug configuration.
ECHO.
ECHO build.bat Release
ECHO Builds the Raspkate with Release configuration.
ECHO.
GOTO End
:BuildDebug
%ms% /p:Configuration="Debug";TargetFrameworkVersion="v4.5.2" Raspkate.sln
GOTO End
:BuildRelease
%ms% /p:Configuration="Release";TargetFrameworkVersion="v4.5.2" Raspkate.sln
GOTO End
:BuildAll
%ms% /p:Configuration="All";TargetFrameworkVersion="v4.5.2" Raspkate.sln
GOTO End
:BuildMinimal
%ms% /p:Configuration="Minimal";TargetFrameworkVersion="v4.5.2" Raspkate.sln
GOTO End
:End
@ECHO ON
View Code
版本一
优化:增加提示编译模式的显示,可以直接运行MSBuildSln.bat或者MSBuildSln.bat debug的模式运行,以及其他界面提醒等
@ECHO OFF
:: 建议使用开发时使用VS的版本对应的MSBuild.exe程序
set ms="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe"
cls
%ms% /version
ECHO,
IF /I "%1"=="Debug" GOTO BuildDebug
IF /I "%1"=="Release" GOTO BuildRelease
IF /I "%1"=="All" GOTO BuildAll
IF /I "%1"=="Minimal" GOTO BuildMinimal
color 0c
ECHO,
ECHO,
echo Do you use this version of MSBuild.exe to compile the current program? Close this window if you don't compile.
echo,&&echo 1:Building projects with Debug models
echo,&&echo 2:Building projects with Release models
echo,&&echo 3:Building projects with Minimal models
echo,&&echo 4:Building projects with All models
echo;
set /p buildType=Please enter number of your build mode :
::pause
color
::GOTO End
IF /I "%buildType%"=="1" GOTO BuildDebug
IF /I "%buildType%"=="2" GOTO BuildRelease
IF /I "%buildType%"=="3" GOTO BuildMinimal
IF /I "%buildType%"=="4" GOTO BuildAll
:ER
ECHO,
ECHO MSBuild.exe Command-Line Build Tool v1.0
ECHO,
ECHO Usage:
ECHO build.bat Debug
ECHO Builds the Solution or Project with Debug configuration.
ECHO,
ECHO build.bat Release
ECHO Builds the Solution or Project with Release configuration.
ECHO,
GOTO End
:BuildDebug
echo you chose Debug build
%ms% /p:Configuration="Debug" Car.sln
echo you chose Debug build completed
GOTO End
:BuildRelease
echo you chose Release build
%ms% /p:Configuration="Release" Car.sln
echo you chose Release build completed
GOTO End
:BuildAll
echo you chose All build
%ms% /p:Configuration="All" Car.sln
echo you chose All build completed
GOTO End
:BuildMinimal
echo you chose Minimal build
%ms% /p:Configuration="Minimal" Car.sln
echo you chose Minimal build completed
GOTO End
:End
pause
@ECHO ON
View Code
版本二
优化:改用参数的方式合并多个编译模式,使用说明,界面提醒等
@ECHO OFF
CLS
ECHO,&ECHO MSBuild.exe Command-Line Build Tool v1.2
:: 建议使用开发时使用VS的版本对应的MSBuild.exe程序
set ms="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe"
echo;&echo ------------------------------[ MSBuild.exe version info ]------------------------------
%ms% /version
echo; &echo ---------------------------------------------------------------------------------------
ECHO;
SET buildType=%~1
IF /I "%buildType%"=="Debug" GOTO BuildSln
IF /I "%buildType%"=="Release" GOTO BuildSln
IF /I "%buildType%"=="All" GOTO BuildSln
IF /I "%buildType%"=="Minimal" GOTO BuildSln
echo,&color 0A
echo Do you use this version of MSBuild.exe to compile the current program?
echo,&&echo 1:Building projects with Debug models
echo,&&echo 2:Building projects with Release models
echo,&&echo 3:Building projects with Minimal models
echo,&&echo 4:Building projects with All models
echo,&&echo Close this window if you don't compile.
set choseNum=0&echo;&set /p choseNum= Please enter number of your build mode :
color
IF /I "%choseNum%"=="1" set buildType=Debug&goto BuildSln
IF /I "%choseNum%"=="2" set buildType=Release&goto BuildSln
IF /I "%choseNum%"=="3" set buildType=All&goto BuildSln
IF /I "%choseNum%"=="4" set buildType=Minimal&goto BuildSln
:ER
CLS&ECHO,&COLOR 0C&ECHO ------------------------------[ Help Info ]------------------------------
ECHO Usage:
ECHO use [ %0 Debug ]
ECHO Builds the Solution or Project with Debug configuration.
ECHO,
ECHO use [ %0 Release ]
ECHO Builds the Solution or Project with Release configuration.
ECHO,
ECHO use [ %0 Minimal ]
ECHO Builds the Solution or Project with Minimal configuration.
ECHO,
ECHO use [ %0 All ]
ECHO Builds the Solution or Project with All configuration.
ECHO,
GOTO End
:BuildSln
echo; &echo BuildSln : you chose [ %buildType% ] build
ping 127.1>nul
%ms% /p:Configuration="%buildType%";Platform=x86 /target:Clean;Rebuild Car.sln
echo; &echo BuildSln : you [ %buildType% ] build completed
GOTO :End
:End
echo;&pause&color
goto :eof
View Code
版本三
优化:1)修复一些bug,2)使用自动颜色。3)使用倒计时
@ECHO OFF
CLS
ECHO,&ECHO MSBuild.exe Command-Line Build Tool v1.2
:: 建议使用开发时使用VS的版本对应的MSBuild.exe程序
set ms="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe"
echo;&echo ---------------------[ MSBuild.exe version info ]---------------------
%ms% /version
echo;&echo ----------------------------------------------------------------------
ECHO;
SET buildType=%~1
IF /I "%buildType%"=="Debug" GOTO BuildSln
IF /I "%buildType%"=="Release" GOTO BuildSln
IF /I "%buildType%"=="All" GOTO BuildSln
IF /I "%buildType%"=="Minimal" GOTO BuildSln
echo,&color 0A
echo Do you use this version of MSBuild.exe to compile the current program?
echo,&&echo 1:Building projects with Debug models
echo,&&echo 2:Building projects with Release models
echo,&&echo 3:Building projects with Minimal models
echo,&&echo 4:Building projects with All models
echo,&&echo Close this window if you don't compile.
set choseNum=0&echo;&set /p choseNum= Please enter number of your build mode :
IF /I "%choseNum%"=="1" set buildType=Debug&goto BuildSln
IF /I "%choseNum%"=="2" set buildType=Release&goto BuildSln
IF /I "%choseNum%"=="3" set buildType=All&goto BuildSln
IF /I "%choseNum%"=="4" set buildType=Minimal&goto BuildSln
:ER
CLS&ECHO,&COLOR 0C&ECHO ---------------------------[ Help Info ]---------------------------
ECHO Usage:
ECHO use [ %0 Debug ]
ECHO Builds the Solution or Project with Debug configuration.
ECHO,
ECHO use [ %0 Release ]
ECHO Builds the Solution or Project with Release configuration.
ECHO,
ECHO use [ %0 Minimal ]
ECHO Builds the Solution or Project with Minimal configuration.
ECHO,
ECHO use [ %0 All ]
ECHO Builds the Solution or Project with All configuration.
ECHO,
GOTO End
:BuildSln
echo;&echo ----------------------------------------------------------------------
echo;&color&echo BuildSln : you chose [ %buildType% ] build
set args=-property:Configuration=%buildType%;Platform=x86 -target:Clean;Rebuild -restore -maxcpucount
echo;&echo BuildSln parameter : %args%
timeout /nobreak /t 15
::%ms% -property:Configuration="%buildType%";Platform=x86 -target:Clean;Rebuild Cares.SMIS.sln -restore -maxcpucount
%ms% Cares.SMIS.sln %args%
echo; &echo BuildSln : you [ %buildType% ] build completed
GOTO :End
:End
echo;&pause
goto :eof
View Code
版本四
优化:1)使用配置项指定解决方案路径,可以把脚本保存在任何路径下执行
@ECHO OFF
CLS
ECHO,&ECHO MSBuild.exe Command-Line Build Tool v1.3
:: 建议使用开发时使用VS的版本对应的MSBuild.exe程序
set ms="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe"
set slnPath="D:\_Del\Car.xxxx.sln"
echo;&echo ---------------------[ MSBuild.exe version info ]---------------------
%ms% /version
echo;&echo ----------------------------------------------------------------------
echo 即将编译解决方案或项目路径:
echo;&echo 【%slnPath%】
echo;&echo ----------------------------------------------------------------------
SET buildType=%~1
IF /I "%buildType%"=="Debug" GOTO BuildSln
IF /I "%buildType%"=="Release" GOTO BuildSln
IF /I "%buildType%"=="All" GOTO BuildSln
IF /I "%buildType%"=="Minimal" GOTO BuildSln
echo,&color 0A
echo Do you use this version of MSBuild.exe to compile the current program?
echo,&&echo 1:Building projects with Debug models
echo,&&echo 2:Building projects with Release models
echo,&&echo 3:Building projects with Minimal models
echo,&&echo 4:Building projects with All models
echo,&&echo Close this window if you don't compile.
set choseNum=0&echo;&set /p choseNum= Please enter number of your build mode :
IF /I "%choseNum%"=="1" set buildType=Debug&goto BuildSln
IF /I "%choseNum%"=="2" set buildType=Release&goto BuildSln
IF /I "%choseNum%"=="3" set buildType=All&goto BuildSln
IF /I "%choseNum%"=="4" set buildType=Minimal&goto BuildSln
:ER
CLS&ECHO,&COLOR 0C&ECHO ---------------------------[ Help Info ]---------------------------
ECHO Usage:
ECHO use [ %0 Debug ]
ECHO Builds the Solution or Project with Debug configuration.
ECHO,
ECHO use [ %0 Release ]
ECHO Builds the Solution or Project with Release configuration.
ECHO,
ECHO use [ %0 Minimal ]
ECHO Builds the Solution or Project with Minimal configuration.
ECHO,
ECHO use [ %0 All ]
ECHO Builds the Solution or Project with All configuration.
ECHO,
GOTO End
:BuildSln
echo;&echo ----------------------------------------------------------------------
echo;&color&echo BuildSln : you chose [ %buildType% ] build
set args=-property:Configuration=%buildType%;Platform=x86 -target:Clean;Rebuild -restore -maxcpucount
echo;&echo BuildSln parameter : %args%
echo;&echo Compiling solution or project path:【%slnPath%】
timeout /nobreak /t 15
::%ms% -property:Configuration="%buildType%";Platform=x86 -target:Clean;Rebuild Car.xxxx.sln -restore -maxcpucount
%ms% %slnPath% %args%
echo; &echo BuildSln : you [ %buildType% ] build completed
GOTO :End
:End
echo;&pause
goto :eof
View Code
您的资助是我最大的动力!金额随意,欢迎来赏!
付款后有任何问题请给我留言。
如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】按钮。
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【关注我】。(●'◡'●)
因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
如果对你有所帮助,赞助一杯咖啡!打
付款后有任何问题请给我留言!!!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/7263841.html
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!
posted on
2017-07-31 16:27
jack_Meng
阅读(15611)
评论(0)
编辑
收藏
举报
会员力量,点亮园子希望
刷新页面返回顶部
导航
博客园
首页
新随笔
联系
订阅
管理
公告
Powered by:
博客园
Copyright © 2024 jack_Meng
Powered by .NET 8.0 on Kubernetes
理解 C# 项目 csproj 文件格式的本质和编译流程_.csproj-CSDN博客
>理解 C# 项目 csproj 文件格式的本质和编译流程_.csproj-CSDN博客
理解 C# 项目 csproj 文件格式的本质和编译流程
最新推荐文章于 2024-03-07 14:53:15 发布
我心依旧
最新推荐文章于 2024-03-07 14:53:15 发布
阅读量929
收藏
5
点赞数
2
文章标签:
c#
wpf
开发语言
原文链接:http://www.fogsvc.com/3024.html
版权
写了这么多个 C# 项目,是否对项目文件 csproj 有一些了解呢?Visual Studio 是怎么让 csproj 中的内容正确显示出来的呢?更深入的,我能够自己扩展 csproj 的功能吗?
本文将直接从 csproj 文件格式的本质来看以上这些问题。
阅读本文,你将:
可以通读 csproj 文件,并说出其中每一行的含义
可以手工修改 csproj 文件,以实现你希望达到的高级功能(更高级的,可以开始写个工具自动完成这样的工作了)
理解新旧 csproj 文件的差异,不至于写工具解析和修改 csproj 文件的时候出现不兼容的错误
csproj 里面是什么?
一、总览 csproj 文件
相信你一定见过传统的 csproj 文件格式。就算你几乎从来没主动去看过里面的内容,在版本管理工具中解冲突时也在里面修改过内容。
不管你是新手还是老手,一定都会觉得这么长这么复杂的文件一定不是给人类阅读的。你说的是对的!传统 csproj 文件中有大量的重复或者相似内容,只为 msbuild 和 Visual Studio 能够识别整个项目的属性和结构,以便正确编译项目。
不过,既然这篇文章的目标是理解 csproj 文件格式的本质,那我当然不会把这么复杂的文件内容直接给你去阅读。
我已经将整个文件结构进行了极度简化,然后用思维导图进行了分割。总结成了下图,如果先不关注文件的细节,是不是更容易看懂了呢?
如果你此前也阅读过我的其他博客,会发现我一直在试图推荐使用新的 csproj 格式:
将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件
让一个 csproj 项目指定多个开发框架
那么新格式和旧格式究竟有哪些不同使得新的格式如此简洁?
于是,我将新的 csproj 文件结构也进行简化,用思维导图进行了分割。总结成了下图:
比较两个思维导图之后,是不是发现其实两者本是相同的格式。如果忽略我在文字颜色上做的标记,其实两者的差异几乎只在文件开头是否有一个 xml 文件标记()。我在文字颜色上的标记代表着这部分的部件是否是可选的,白色代表必须,灰色代表可选;而更接近背景色的灰色代表一般情况下都是不需要的。
我把两个思维导图放到一起方便比较:
会发现,传统格式中 xml 声明、Project 节点、Import (props)、PropertyGroup、ItemGroup、Import (targets) 都是必要的,而新格式中只有 Project 节点 和 PropertyGroup 是必要的。
是什么导致了这样的差异?在了解 csproj 文件中各个部件的作用之前,这似乎很难回答。
二、了解 csproj 中的各个部件的作用
xml 声明部分完全没有在此解释的必要了,为兼容性提供了方便,详见:XML – Wikipedia。
接下来,我们不会依照部件出现的顺序安排描述的顺序,而是按照关注程度排序。
1.PropertyGroup
PropertyGroup 是用来存放属性的地方,这与它的名字非常契合。那么里面放什么属性呢?答案是——什么都能放!
在这里写属性就像在代码中定义属性或变量一样,只要写了,就会生成一个指定名称的属性。
比如,我们写:
walterlv is a 逗比
那么,就会生成一个 Foo 属性,值为字符串 walterlv is a 逗比。至于这个属性有什么用,那就不归这里管了。
这些属性的含义完全是由外部来决定的,例如在旧的 csproj 格式中,编译过程中会使用 TargetFrameworkVersion 属性,以确定编译应该使用的 .NET Framework 目标框架的版本(是 v4.5 还是 v4.7)。在新的 csproj 格式中,编译过程会使用 TargetFrameworks 属性来决定编译应该使用的目标框架(是 net47 还是 netstandard2.0)。具体是编译过程中的哪个环节哪个组件使用了此属性,我们后面会说。
从这个角度来说,如果你没有任何地方用到了你定义的属性,那为什么还要定义它呢?是的——这只是浪费。
PropertyGroup 可以定义很多个,里面都可以同等地放属性。至于为什么会定义多个,原因无外乎两个:
为了可读性——将一组相关的属性放在一起,便于阅读和理解意图(旧的 csproj 谈不上什么可读性)
为了加条件——有的属性在 Debug 和 Release 下不一样(例如条件编译符 DefineConstants)
额外说一下,Debug 和 Release 这两个值其实是在某处一个名为 Configuration 的属性定义的,它们其实只是普通的字符串而已,没什么特殊的意义,只是有很多的 PropertyGroup 加上了 Debug Release 的判断条件才使得不同的 Configuration 具有不同的其他属性,最终表现为编译后的巨大差异。由于 Configuration 属性可以放任意字符串,所以甚至可以定义一个非 Debug 和 Release 的配置(例如用于性能专项测试)也是可以的。
2.ItemGroup
ItemGroup 是用来指定集合的地方,这与它的名字非常契合。那么这集合里面放什么项呢?答案是——什么都能放!
是不是觉得这句话跟前面的 PropertyGroup 句式一模一样?是的——就是一模一样!csproj 中的两个大头都这样不带语义,几乎可以说明 csproj 文件是不包含语义的,它能够用来做什么事情纯属由其他模块来指定;这为 csproj 文件强大的扩展性提供了格式基础。
既然什么都能放,那我们放这些吧:
walterlv is a 逗比walterlv is a 天才天才向左,逗比向右逗比属性额外加成
于是我们就有 4 个类型为 Foo 的项了,至于这 4 个 Foo 项有什么作用,那就不归这里管了。
这些项的含义与 PropertyGroup 一样也是由外部来决定。具体是哪个外部,我们稍后会说。但是我们依然有一些常见的项可以先介绍介绍:
Reference 引用某个程序集PackageReference 引用某个 NuGet 包ProjectReference 引用某个项目Compile 常规的 C# 编译None 没啥特别的编译选项,就为了执行一些通用的操作(或者是只是为了在 Visual Studio 列表中能够有一个显示)Folder 一个空的文件夹,也没啥用(不过标了这个文件夹,Visual Studio 中就能有一个文件夹的显式,即便实际上这个文件夹可能不存在)
ItemGroup 也可以放很多个,一样是为了提升可读性或者增加条件。
3.Import
你应该注意到在前面的思维导图中,无论是新 csproj 还是旧 csproj 文件,我都写了两个 Import 节点。其实它们本质上是完全一样的,只不过在含义上有不同。前面我们了解到 csproj 文件致力于脱离语义,所以分开两个地方写几乎只是为了可读性考虑。
那么前面那个 Import 和后面的 Import 在含义上有何区别?思维导图的括号中我已说明了含义。前面是为了导入属性(props),后面是为了导入 Targets。属性就是前面 PropertyGroup 中说的那些属性和 ItemGroup 里说的那些项;而 Targets 是新东西,这才是真正用来定义编译流程的关键,由于 Targets 是所有节点里面最复杂的部分,所以我们放到最后再说。
那么,被我们 Import 进来的那些文件是什么呢?用两种扩展名,定义属性的那一种是 .props,定义行为的那一种是 .targets。
这两种文件除了含义不同以外,内容的格式都是完全一样的——而且——就是 csproj 文件的那种格式!没错,也包含 Project、Import、PropertyGroup、ItemGroup、Targets。只不过,相比于对完整性有要求的 csproj 文件来说,这里可以省略更多的节点。由于有 Import 的存在,所以一层一层地嵌套 props 或者 targets 都是可能的。
说了这么多,让我们来看其中两个 .props 文件吧。
先看看旧格式 csproj 文件中第一行一定会 Import 的那个 Microsoft.Common.props。
truetruetruetruetrue
文件太长,做了大量删减,但也可以看到文件格式与 csproj 几乎是一样的。此文件中,根据其他属性的值有条件地定义了另一些属性。
再看看另一个 MSTest 单元测试项目中被隐式 Import 进 csproj 文件中的 .props 文件。(所谓隐式地 Import,只不过是被间接地引入,在 csproj 文件中看不到这个文件名而已。至于如何间接引入,因为涉及到 Targets,所以后面一起说明。)
Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.dllPreserveNewestFalseMicrosoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.dllPreserveNewestFalseMicrosoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.dllPreserveNewestFalse
此文件中将三个 dll 文件从 MSTest 的 NuGet 包中以链接的形式包含到项目中,并且此文件在 Visual Studio 的解决方案列表中不可见。
可以看出,引入的 props 文件可以实现几乎与 csproj 文件中一样的功能。
那么,既然 csproj 文件中可以完全实现这样的功能,为何还要单独用 props 文件来存放呢?原因显而易见了——为了在多个项目中使用,一处更新,到处生效。所以有没有觉得很好玩——如果把版本号单独放到 props 文件中,就能做到一处更新版本号,到处更新版本号啦!
4.Target
终于开始说 Target 了。为什么会这么期待呢?因为前面埋下的各种伏笔几乎都要在这一节点得到解释了。
一般来说,Target 节点写在 csproj 文件的末尾,但这个并不是强制的。Targets 是一种非常强大的功能扩展方式,支持 msbuild 预定义的一些指令,支持命令行,甚至支持使用 C# 直接编写(当然编译成 dll 会更方便些),还支持这些的排列组合和顺序安排。而我们实质上的编译过程便全部由这些 Targets 来完成。我们甚至可以直接说——编译过程就是靠这些 Target 的组合来完成的。
如果你希望全面了解 Targets,推荐直接阅读微软的官方文档 MSBuild Targets,而本文只会对其进行一些简单的概述(我即将用另一篇博客来详细讲解,不然这篇就太长了)。
不过,为了简单地理解 Target,我依然需要借用官方文档的例子作为开头。
这份代码定义了一个名为 Construct 的 Target,这是随意取的一个名字,并不重要——但是编译过程中会执行这个 Target。在这个 Target 内部,使用了一个 msbuild 自带的名为 Csc 的 Task。这里我们再次引入了一个新的概念 Task。而 Task 是 Target内部真正完成逻辑性任务的核心;或者说 Target 其实只是一种容器,本身并不包含编译逻辑,但它的内部可以存放 Task 来实现编译逻辑。一个 Target 内可以放多个 Task,不止如此,还能放 PropertyGroup 和 ItemGroup,不过这是仅在编译期生效的属性和项了。
@(Compile) 是 ItemGroup 中所有 Compile 类型节点的集合。还记得我们在 ItemGroup 小节时说到每一种 Item 的含义由外部定义吗?是的,就是在这里定义的!本身并没有什么含义,但它们作为参数传入到了具体的 Task 之后便有了此 Task 指定的含义。
于是 的含义便是调用 msbuild 内置的 C# 编译器编译所有 Compile 类型的项。
如果后面定义了一个跟此名称一样的 Target,那么后一个 Target 就会覆盖前一个 Target,导致前一个 Target 失效。
再次回到传统的 csproj 文件上来,每一个传统格式的 csproj 都有这样一行:
而引入的这份 .targets 文件便包含了 msbuild 定义的各种核心编译任务。只要引入了这个 .targets 文件,便能使用 msbuild 自带的编译任务完成绝大多数项目的编译。你可以自己去查看此文件中的内容,相信有以上 Target 的简单介绍,应该能大致理解其完成编译的流程。这是我的地址:C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Microsoft.CSharp.targets。
5.Project
所有的 csproj 文件都是以 Project 节点为根节点。既然是根节点为何我会在最后才说 Project 呢?因为这可是一个大悬念啊!本文一开始就描述了新旧两款 csproj 文件格式的差异,你也能从我的多篇博客中感受到新格式带来的各种好处;而简洁便是新格式中最大的好处之一。它是怎么做到简洁的呢?
就靠 Project 节点了。
注意到新格式中 Project 节点有 Sdk 属性吗?因为有此属性的存在,csproj 文件才能如此简洁。因为——所谓 Sdk,其实是一大波 .targets 文件的集合。它帮我们导入了公共的属性、公共的编译任务,还帮我们自动将项目文件夹下所有的 **\*.cs 文件都作为 ItemGroup 的项引入进来。
如果你希望看看 Microsoft.NET.Sdk 都引入了哪些文件,可以去本机安装的 msbuild 或 dotnet 的目录下查看。当我使用 msbuild 编译时,我的地址:C:\Program Files\dotnet\sdk\2.1.200\Sdks\Microsoft.NET.Sdk\build\。比如你可以从此文件夹里的 Microsoft.NET.GenerateAssemblyInfo.targets 文件中发现 AssemblyInfo.cs 文件是如何自动生成及生效的。
编译器是如何将这些零散的部件组织起来的?
这里说的编译器几乎只指 msbuild 和 Roslyn,前者基于 .NET Framework,后者基于 .NET Core。不过,它们在处理我们的项目文件时的行为大多是一致的——至少对于通常项目来说如此。
我们前一部分介绍每个部件的时候,已经简单说了其组织方式,这里我们进行一个回顾和总结。
当 Visual Studio 打开项目时,它会解析里面所有的 Import 节点,确认应该引入的 .props 和 .targets 文件都引入了。随后根据 PropertyGroup 里面设置的属性正确显示属性面板中的状态,根据 ItemGroup 中的项正确显示解决方案管理器中的引用列表、文件列表。——这只是 Visual Studio 做的事情。
在编译时,msbuild 或 Roslyn 还会重新做一遍上面的事情——毕竟这两个才是真正的编译器,可不是 Visual Studio 的一部分啊。随后,执行编译过程。它们会按照 Target 指定的先后顺序来安排不同 Target 的执行,当执行完所有的 Target,便完成了编译过程。
新旧 csproj 在编译过程上有什么差异?
相信读完前面两个部分之后,你应该已经了解到在格式本身上,新旧格式之间其实并没有什么差异。或者更严格来说,差异只有一条——新格式在 Project 上指定了 Sdk。真正造成新旧格式在行为上的差别来源于默认为我们项目 Import 进来的那些 .props 和 .targets 不同。新格式通过 Microsoft.NET.Sdk 为我们导入了更现代化的 .props 和 .targets,而旧格式需要考虑到兼容性压力,只能引入旧的那些 .targets。
新的 Microsoft.NET.Sdk 以不兼容的方式支持了各种新属性,例如新的 TargetFrameworks 代替旧的 TargetFrameworkVersion,使得我们的 C# 项目可以脱离 .NET Framework,引入其他各种各样的目标框架,例如 netstandard2.0、net472、uap10.0 等(可以参考 从以前的项目格式迁移到 VS2017 新项目格式 – 林德熙)了解可以使用那些目标框架。
新的 Microsoft.NET.Sdk 以不兼容的方式原生支持了 NuGet 包管理。也就是说我们可以在不修改 csproj 的情况之下通过 NuGet 包来扩展 csproj 的功能。而旧的格式需要在 csproj 文件的末尾添加如下代码才可以获得其中一个 NuGet 包功能的支持:
不过好在 NuGet 4.x 以上版本在安装 NuGet 包时自动为我们在 csproj 中插入了以上代码。
优惠劵
我心依旧
关注
关注
2
点赞
踩
5
收藏
觉得还不错?
一键收藏
知道了
0
评论
理解 C# 项目 csproj 文件格式的本质和编译流程
写了这么多个 C# 项目,是否对项目文件 csproj 有一些了解呢?Visual Studio 是怎么让 csproj 中的内容正确显示出来的呢?更深入的,我能够自己扩展 csproj 的功能吗?本文将直接从 csproj 文件格式的本质来看以上这些问题。
复制链接
扫一扫
获取C#项目包含的所有程序文件的源代码
12-12
获取C#项目包含的所有程序文件的源代码,包含项目文件SLN的解析,解决方案CSPROJ的解析,XML命名空间的适配。
“csproj文件究竟是做什么用的”
weixin_30413739的博客
08-17
572
csproj文件大家应该不会陌生,那就是C#项目文件的扩展名,它是“C Sharp Project”的缩写。 那么它究竟是给谁用的呢?那是给开发工具用的,例如我们在熟悉不过的Visual Studio,以及大家可以没有接触过,但是应该都听说过的MSBuild.exe。Visual Studio会根据csproj里的XML定义来管理项目文件以及相关其他一些种类非常丰富的数据及操作,MSBuild也会...
参与评论
您还未登录,请先
登录
后发表或查看评论
csproj内容解析
sgmcumt的博客
10-10
6980
文章目录指定目标框架指定多个目标框架新增其它项目属性项目引用普通NuGet包引用添加引用NuGet包的条件托管程序集引用添加COM组件引用本机文件引用项目引用编译嵌入式资源None输入其它
使用C#很长时间都没太关注,最近查看一些开源软件,有时候需要在csproj更改项目的配置信息,不得不熟悉里面的配置内容。
如果只是想了解csproj文件的配置项的含义,不太关注配置内容的细节,可以查看理解 C#...
vs2019 .NET CORE csproj 文件编辑点
pehao的博客
10-19
1297
1. 引用框架,Microsoft.NETCore.App,手动打开xxx.csproj文件,添加以下节点
2.输出时,不输出\bin\debug\netcore3.1目录
MSBuild 中的 PropertyGroup、ItemGroup 和 ItemMetadata
aijianxie8808的博客
04-22
318
在软件项目不断的进展中,MSBuild 脚本可能几个月都不会被修改,因为通常编译和发布的目录是不经常变化的。
但,一旦某天你需要修改了,看到那一堆 $(Something)、 @(Something)、%(Something) 是相当的头大,不得不搜索 MSDN 才能找到合理的用法。
每次看到下面这样的语法,我都感觉,有必要把语法设计成这样吗?
1 .csproj 文件 热门推荐 m0_37805255的博客 08-28 1万+ .csproj 文件 .csproj,是C#项目文件的扩展名,它是“C Sharp Project”的缩写。.net开发环境中建立项目时,会产生.csproj文件,这是C#的工程文件,其中记录了与工程有关的相关信息,例如包含的文件,程序的版本,所生成的文件的类型和位置信息等。 【作用】 .csproj究竟是做什么用的?它是给开发工具用的,例如我们再熟悉不过的Visual Studio,以... csproj文件常用设置及C#注释常用写法 博客 06-29 774 csproj文件常用设置及C#注释常用写法 修改.csproj文件_从.NET Core将现有.NET项目文件升级为精益的新CSPROJ格式 10-13 1055 修改.csproj文件If you've looked at csproj (C# (csharp) projects) in the past in a text editor you probably looked away quickly. They are effectively MSBuild files that orchestrate the build process. Phras... 【CSharp】关于xxx.csproj文件的理解 jn10010537的博客 07-21 593 Visual Studio会根据csproj里的内容来定义来管理项目文件以及相关其他一些种类非常丰富的数据及操作。.csproj文件记录了与工程有关的相关信息,例如包含的文件,程序的版本,所生成的文件的类型和位置信息等。在.NET框架的开发环境中建立项目时,会产生.csproj文件,这是C#的项目工程文件。csproj的全称是C Sharp Project的缩写,是C#项目文件的扩展名。上面的iRayBase.csproj 文件后缀是 .csproj。在示例代码里,遇到.csproj 文件。 C#动态执行与编译 09-14 C#动态执行与编译,实现了动态编译并执行指定类(代码)的函数的方法。 拖放打开文件,C#获取文件目录路径 03-16 摘要:C#源码,文件操作,获取路径,拖放文件 拖放打开文件,C#获取文件的目录或路径信息,只需拖动文件到主窗体中,即可获取到所选文件所在的目录路径,弹出窗口告诉你。这种拖放打开文件的方法也是Windows系统所特有... 使用.NET命令行编译器编译项目(如ASP.NET、C#等) 01-21 源程序最好有.csproj或.vbproj文件,没有的话,要花些时间调试 下面我以VB.NET做示例讲解一下: 从proj我们可以获取以下有用信息 Settings小节中有很多配置选项,对应一些编译器选项 小节中是项目的引用,第3... C#二维码识别和生成的源码,VS2017直接编译 03-16 Zxing库的源码,C#语言 ,VS编译器,.net4.0以上框架支持,包含二维码生成和识别模块,支持常规一维条形码,QR、DM等二维码,进行了识别优化,测试成功率99%。 1768.交替合并字符串 明确的爱,真诚的喜欢,直接的厌恶,站在太阳底下的坦荡,被坚定的选择。 03-07 152 给你两个字符串 word1 和 word2。请你从 word1 开始,通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长,就将多出来的字母追加到合并后字符串的末尾。使用两个指针i和j,初始时分别指向两个字符串的首个位置。如果i没有超出word1的范围,就将word1[i]加入答案,并且将i移动一个位置;如果j没有超出word2的范围,就将word2[j]加入答案,并且将j移动一个位置。当i和j都超出对应的范围后,结束循环并返回答案即可。返回 合并后的字符串。 C#通过配置文件动态修改web.config内容 lxyforever5的博客 03-07 338 Web.setting.config内容,存放一些配置信息,内容具体情况具体设置。Web.aaa.config内容,存放连接数据库的信息。1. Web.config配置文件内的处理。3.进行动态修改,具体情况具体操作。 [C#]winform部署yolov9的onnx模型 FL1623863129的博客 03-04 931 C#实现全网yolov7目前最快winform目标检测,使用C#部署openvino-yolov5s模型,使用C++部署yolov8的onnx和bytetrack实现目标追踪,用opencv和onnxruntime去部署yolov5-7-8,使用C#调用libotrch-yolov5模型实现全网最快winform目标检测。这不仅展示了YOLO系列模型在实际应用中的价值,也体现了C# WinForms在构建用户界面和集成深度学习模型方面的优势。在当今的计算机视觉领域,目标检测是不可或缺的一项技术。 C# 不可识别数据库格式问题 hspx668的博客 03-04 898 可以尝试使用数据库管理工具(比如Access自带的修复工具)对数据库文件进行修复,或者尝试连接其他已知可用的数据库文件进行测试。5. 使用正确的连接字符串:在连接数据库时,需要使用正确的连接字符串来指定数据库文件的位置、类型和其他必要信息。总之,当遇到C#中不可识别的数据库格式错误时,重要的是要仔细检查并排除各种可能导致问题的原因,并采取适当的措施来解决问题,以确保应用程序能够顺利地连接和操作数据库。总之,当遇到数据库格式不可识别的错误时,首先需要仔细检查错误消息,确定出现错误的具体位置和原因。 ManualResetEvent 在线程中的使用C# 最新发布 weixin_40314351的博客 03-07 365 ManualResetEvent 用于表示线程同步事件,可以使得线程等待信号发射之后才继续执行下一步,否则一直处于等待状态中。 c#如何生成csproj文件 07-28 生成一个 C# 的 csproj 文件可以通过以下步骤完成: 1. 打开 Visual Studio 或者你喜欢的代码编辑器。 2. 创建一个新的 C# 项目或者打开一个已有的项目。 3. 在项目文件夹中找到一个以 .csproj 结尾的文件,例如 `MyProject.csproj`。 4. 打开这个文件,你可以使用文本编辑器或者代码编辑器来编辑它。 5. csproj 文件是一个 XML 格式的文件,其中包含了项目的配置信息。你可以根据需要添加、修改或删除一些元素。 6. 例如,你可以添加 ` 7. 你还可以添加 ` 8. 修改完毕后,保存 csproj 文件。 9. 在 Visual Studio 中,你可以右键点击项目,选择重新加载项目,以使修改生效。如果你在命令行中进行操作,则无需重新加载项目。 通过这些步骤,你就可以生成一个 C# 的 csproj 文件了。请记得根据项目的需要进行相应的配置和修改。 “相关推荐”对你有帮助么? 非常没帮助 没帮助 一般 有帮助 非常有帮助 提交 我心依旧 CSDN认证博客专家 CSDN认证企业博客 码龄17年 暂无认证 5 原创 47万+ 周排名 15万+ 总排名 4821 访问 等级 74 积分 1 粉丝 2 获赞 1 评论 5 收藏 私信 关注 热门文章 xLang 的类型转换 2169 理解 C# 项目 csproj 文件格式的本质和编译流程 928 用xLang写Timer事件 726 用xLang 写 SQL 控制程序 510 简单控制 xLang 窗体 260 分类专栏 xLang&xStudio 4篇 最新评论 xLang 的一些常见故障和语法问题 CSDN-Ada助手: 恭喜作者发布了第7篇博客!不断分享关于xLang 的常见故障和语法问题,对于我们这些初学者来说,真的是非常有帮助。希望作者能够继续保持创作的热情,也希望能够看到更多关于xLang 的深入学习和应用案例的分享。加油!期待您的下一篇文章! 您愿意向朋友推荐“博客详情页”吗? 强烈不推荐 不推荐 一般般 推荐 强烈推荐 提交 最新文章 xLang 的一些常见故障和语法问题 用msbuild自动创建nuget软件包 简单控制 xLang 窗体 2023年3篇 2020年4篇 目录 目录 分类专栏 xLang&xStudio 4篇 目录 评论 被折叠的 条评论 为什么被折叠? 到【灌水乐园】发言 查看更多评论 添加红包 祝福语 请填写红包祝福语或标题 红包数量 个 红包个数最小为10个 红包总金额 元 红包金额最低5元 余额支付 当前余额3.43元 前往充值 > 需支付:10.00元 取消 确定 下一步 知道了 成就一亿技术人! 领取后你会自动成为博主和红包主的粉丝 规则 hope_wisdom 发出的红包 实付元 使用余额支付 点击重新获取 扫码支付 钱包余额 0 抵扣说明: 1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。 余额充值理解 C# 项目 csproj 文件格式的本质和编译流程 - 简书
# 项目 csproj 文件格式的本质和编译流程 - 简书登录注册写文章首页下载APP会员IT技术理解 C# 项目 csproj 文件格式的本质和编译流程欲与星辰眠关注赞赏支持理解 C# 项目 csproj 文件格式的本质和编译流程写了这么多个 C# 项目,是否对项目文件 csproj 有一些了解呢?Visual Studio 是怎么让 csproj 中的内容正确显示出来的呢?更深入的,我能够自己扩展 csproj 的功能吗?本文将直接从 csproj 文件格式的本质来看以上这些问题。阅读本文,你将:可以通读 csproj 文件,并说出其中每一行的含义可以手工修改 csproj 文件,以实现你希望达到的高级功能(更高级的,可以开始写个工具自动完成这样的工作了)理解新旧 csproj 文件的差异,不至于写工具解析和修改 csproj 文件的时候出现不兼容的错误csproj 里面是什么?总览 csproj 文件相信你一定见过传统的 csproj 文件格式。就算你几乎从来没主动去看过里面的内容,在版本管理工具中解冲突时也在里面修改过内容。不管你是新手还是老手,一定都会觉得这么长这么复杂的文件一定不是给人类阅读的。你说的是对的!传统 csproj 文件中有大量的重复或者相似内容,只为 msbuild 和 Visual Studio 能够识别整个项目的属性和结构,以便正确编译项目。不过,既然这篇文章的目标是理解 csproj 文件格式的本质,那我当然不会把这么复杂的文件内容直接给你去阅读。我已经将整个文件结构进行了极度简化,然后用思维导图进行了分割。总结成了下图,如果先不关注文件的细节,是不是更容易看懂了呢?
如果你此前也阅读过我的其他博客,会发现我一直在试图推荐使用新的 csproj 格式:将 WPF、UWP 以及其他各种类型的旧样式的 csproj 文件迁移成新样式的 csproj 文件让一个 csproj 项目指定多个开发框架那么新格式和旧格式究竟有哪些不同使得新的格式如此简洁?于是,我将新的 csproj 文件结构也进行简化,用思维导图进行了分割。总结成了下图:
比较两个思维导图之后,是不是发现其实两者本是相同的格式。如果忽略我在文字颜色上做的标记,其实两者的差异几乎只在文件开头是否有一个 xml 文件标记()。我在文字颜色上的标记代表着这部分的部件是否是可选的,白色代表必须,灰色代表可选;而更接近背景色的灰色代表一般情况下都是不需要的。我把两个思维导图放到一起方便比较:
会发现,传统格式中 xml 声明、Project 节点、Import (props)、PropertyGroup、ItemGroup、Import (targets) 都是必要的,而新格式中只有 Project 节点 和 PropertyGroup 是必要的。是什么导致了这样的差异?在了解 csproj 文件中各个部件的作用之前,这似乎很难回答。了解 csproj 中的各个部件的作用xml 声明部分完全没有在此解释的必要了,为兼容性提供了方便,详见:XML - Wikipedia。接下来,我们不会依照部件出现的顺序安排描述的顺序,而是按照关注程度排序。PropertyGroupPropertyGroup 是用来存放属性的地方,这与它的名字非常契合。那么里面放什么属性呢?答案是——什么都能放!在这里写属性就像在代码中定义属性或变量一样,只要写了,就会生成一个指定名称的属性。比如,我们写:walterlv is a 逗比那么,就会生成一个 Foo 属性,值为字符串 walterlv is a 逗比。至于这个属性有什么用,那就不归这里管了。这些属性的含义完全是由外部来决定的,例如在旧的 csproj 格式中,编译过程中会使用 TargetFrameworkVersion 属性,以确定编译应该使用的 .NET Framework 目标框架的版本(是 v4.5 还是 v4.7)。在新的 csproj 格式中,编译过程会使用 TargetFrameworks 属性来决定编译应该使用的目标框架(是 net47 还是 netstandard2.0)。具体是编译过程中的哪个环节哪个组件使用了此属性,我们后面会说。从这个角度来说,如果你没有任何地方用到了你定义的属性,那为什么还要定义它呢?是的——这只是浪费。PropertyGroup 可以定义很多个,里面都可以同等地放属性。至于为什么会定义多个,原因无外乎两个:为了可读性——将一组相关的属性放在一起,便于阅读和理解意图(旧的 csproj 谈不上什么可读性)为了加条件——有的属性在 Debug 和 Release 下不一样(例如条件编译符 DefineConstants)额外说一下,Debug 和 Release 这两个值其实是在某处一个名为 Configuration 的属性定义的,它们其实只是普通的字符串而已,没什么特殊的意义,只是有很多的 PropertyGroup 加上了 Debug Release 的判断条件才使得不同的 Configuration 具有不同的其他属性,最终表现为编译后的巨大差异。由于 Configuration 属性可以放任意字符串,所以甚至可以定义一个非 Debug 和 Release 的配置(例如用于性能专项测试)也是可以的。ItemGroupItemGroup 是用来指定集合的地方,这与它的名字非常契合。那么这集合里面放什么项呢?答案是——什么都能放!是不是觉得这句话跟前面的 PropertyGroup 句式一模一样?是的——就是一模一样!csproj 中的两个大头都这样不带语义,几乎可以说明 csproj 文件是不包含语义的,它能够用来做什么事情纯属由其他模块来指定;这为 csproj 文件强大的扩展性提供了格式基础。既然什么都能放,那我们放这些吧:walterlv is a 逗比walterlv is a 天才天才向左,逗比向右逗比属性额外加成于是我们就有 4 个类型为 Foo 的项了,至于这 4 个 Foo 项有什么作用,那就不归这里管了。这些项的含义与 PropertyGroup 一样也是由外部来决定。具体是哪个外部,我们稍后会说。但是我们依然有一些常见的项可以先介绍介绍:Reference 引用某个程序集PackageReference 引用某个 NuGet 包ProjectReference 引用某个项目Compile 常规的 C# 编译None 没啥特别的编译选项,就为了执行一些通用的操作(或者是只是为了在 Visual Studio 列表中能够有一个显示)Folder 一个空的文件夹,也没啥用(不过标了这个文件夹,Visual Studio 中就能有一个文件夹的显式,即便实际上这个文件夹可能不存在)ItemGroup 也可以放很多组,一样是为了提升可读性或者增加条件。Import你应该注意到在前面的思维导图中,无论是新 csproj 还是旧 csproj 文件,我都写了两个 Import 节点。其实它们本质上是完全一样的,只不过在含义上有不同。前面我们了解到 csproj 文件致力于脱离语义,所以分开两个地方写几乎只是为了可读性考虑。那么前面那个 Import 和后面的 Import 在含义上有何区别?思维导图的括号中我已说明了含义。前面是为了导入属性(props),后面是为了导入 Targets。属性就是前面 PropertyGroup 中说的那些属性和 ItemGroup 里说的那些项;而 Targets 是新东西,这才是真正用来定义编译流程的关键,由于 Targets 是所有节点里面最复杂的部分,所以我们放到最后再说。那么,被我们 Import 进来的那些文件是什么呢?用两种扩展名,定义属性的那一种是 .props,定义行为的那一种是 .targets。这两种文件除了含义不同以外,内容的格式都是完全一样的——而且——就是 csproj 文件的那种格式!没错,也包含 Project、Import、PropertyGroup、ItemGroup、Targets。只不过,相比于对完整性有要求的 csproj 文件来说,这里可以省略更多的节点。由于有 Import 的存在,所以一层一层地嵌套 props 或者 targets 都是可能的。说了这么多,让我们来看其中两个 .props 文件吧。先看看旧格式 csproj 文件中第一行一定会 Import 的那个 Microsoft.Common.props。truetruetruetruetrue文件太长,做了大量删减,但也可以看到文件格式与 csproj 几乎是一样的。此文件中,根据其他属性的值有条件地定义了另一些属性。再看看另一个 MSTest 单元测试项目中被隐式 Import 进 csproj 文件中的 .props 文件。(所谓隐式地 Import,只不过是被间接地引入,在 csproj 文件中看不到这个文件名而已。至于如何间接引入,因为涉及到 Targets,所以后面一起说明。)Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.dllPreserveNewestFalseMicrosoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.dllPreserveNewestFalseMicrosoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.dllPreserveNewestFalse此文件中将三个 dll 文件从 MSTest 的 NuGet 包中以链接的形式包含到项目中,并且此文件在 Visual Studio 的解决方案列表中不可见。可以看出,引入的 props 文件可以实现几乎与 csproj 文件中一样的功能。那么,既然 csproj 文件中可以完全实现这样的功能,为何还要单独用 props 文件来存放呢?原因显而易见了——为了在多个项目中使用,一处更新,到处生效。所以有没有觉得很好玩——如果把版本号单独放到 props 文件中,就能做到一处更新版本号,到处更新版本号啦!Target终于开始说 Target 了。为什么会这么期待呢?因为前面埋下的各种伏笔几乎都要在这一节点得到解释了。
一般来说,Target 节点写在 csproj 文件的末尾,但这个并不是强制的。Targets 是一种非常强大的功能扩展方式,支持 msbuild 预定义的一些指令,支持命令行,甚至支持使用 C# 直接编写(当然编译成 dll 会更方便些),还支持这些的排列组合和顺序安排。而我们实质上的编译过程便全部由这些 Targets 来完成。我们甚至可以直接说——编译过程就是靠这些 Target 的组合来完成的。如果你希望全面了解 Targets,推荐直接阅读微软的官方文档 MSBuild Targets,而本文只会对其进行一些简单的概述(我即将用另一篇博客来详细讲解,不然这篇就太长了)。不过,为了简单地理解 Target,我依然需要借用官方文档的例子作为开头。这份代码定义了一个名为 Construct 的 Target,这是随意取的一个名字,并不重要——但是编译过程中会执行这个 Target。在这个 Target 内部,使用了一个 msbuild 自带的名为 Csc 的 Task。这里我们再次引入了一个新的概念 Task。而 Task 是 Target内部真正完成逻辑性任务的核心;或者说 Target 其实只是一种容器,本身并不包含编译逻辑,但它的内部可以存放 Task 来实现编译逻辑。一个 Target 内可以放多个 Task,不止如此,还能放 PropertyGroup 和 ItemGroup,不过这是仅在编译期生效的属性和项了。@(Compile) 是 ItemGroup 中所有 Compile 类型节点的集合。还记得我们在 ItemGroup 小节时说到每一种 Item 的含义由外部定义吗?是的,就是在这里定义的!本身并没有什么含义,但它们作为参数传入到了具体的 Task 之后便有了此 Task 指定的含义。于是 的含义便是调用 msbuild 内置的 C# 编译器编译所有 Compile 类型的项。如果后面定义了一个跟此名称一样的 Target,那么后一个 Target 就会覆盖前一个 Target,导致前一个 Target 失效。再次回到传统的 csproj 文件上来,每一个传统格式的 csproj 都有这样一行:而引入的这份 .targets 文件便包含了 msbuild 定义的各种核心编译任务。只要引入了这个 .targets 文件,便能使用 msbuild 自带的编译任务完成绝大多数项目的编译。你可以自己去查看此文件中的内容,相信有以上 Target 的简单介绍,应该能大致理解其完成编译的流程。这是我的地址:C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Microsoft.CSharp.targets。Project所有的 csproj 文件都是以 Project 节点为根节点。既然是根节点为何我会在最后才说 Project 呢?因为这可是一个大悬念啊!本文一开始就描述了新旧两款 csproj 文件格式的差异,你也能从我的多篇博客中感受到新格式带来的各种好处;而简洁便是新格式中最大的好处之一。它是怎么做到简洁的呢?就靠 Project 节点了。注意到新格式中 Project 节点有 Sdk 属性吗?因为有此属性的存在,csproj 文件才能如此简洁。因为——所谓 Sdk,其实是一大波 .targets 文件的集合。它帮我们导入了公共的属性、公共的编译任务,还帮我们自动将项目文件夹下所有的 **\*.cs 文件都作为 ItemGroup 的项引入进来。如果你希望看看 Microsoft.NET.Sdk 都引入了哪些文件,可以去本机安装的 msbuild 或 dotnet 的目录下查看。当我使用 msbuild 编译时,我的地址:C:\Program Files\dotnet\sdk\2.1.200\Sdks\Microsoft.NET.Sdk\build\。比如你可以从此文件夹里的 Microsoft.NET.GenerateAssemblyInfo.targets 文件中发现 AssemblyInfo.cs 文件是如何自动生成及生效的。编译器是如何将这些零散的部件组织起来的?这里说的编译器几乎只指 msbuild 和 Roslyn,前者基于 .NET Framework,后者基于 .NET Core。不过,它们在处理我们的项目文件时的行为大多是一致的——至少对于通常项目来说如此。我们前一部分介绍每个部件的时候,已经简单说了其组织方式,这里我们进行一个回顾和总结。当 Visual Studio 打开项目时,它会解析里面所有的 Import 节点,确认应该引入的 .props 和 .targets 文件都引入了。随后根据 PropertyGroup 里面设置的属性正确显示属性面板中的状态,根据 ItemGroup 中的项正确显示解决方案管理器中的引用列表、文件列表。——这只是 Visual Studio 做的事情。在编译时,msbuild 或 Roslyn 还会重新做一遍上面的事情——毕竟这两个才是真正的编译器,可不是 Visual Studio 的一部分啊。随后,执行编译过程。它们会按照 Target 指定的先后顺序来安排不同 Target 的执行,当执行完所有的 Target,便完成了编译过程。新旧 csproj 在编译过程上有什么差异?相信读完前面两个部分之后,你应该已经了解到在格式本身上,新旧格式之间其实并没有什么差异。或者更严格来说,差异只有一条——新格式在 Project 上指定了 Sdk。真正造成新旧格式在行为上的差别来源于默认为我们项目 Import 进来的那些 .props 和 .targets 不同。新格式通过 Microsoft.NET.Sdk 为我们导入了更现代化的 .props 和 .targets,而旧格式需要考虑到兼容性压力,只能引入旧的那些 .targets。新的 Microsoft.NET.Sdk 以不兼容的方式支持了各种新属性,例如新的 TargetFrameworks 代替旧的 TargetFrameworkVersion,使得我们的 C# 项目可以脱离 .NET Framework,引入其他各种各样的目标框架,例如 netstandard2.0、net472、uap10.0 等(可以参考 从以前的项目格式迁移到 VS2017 新项目格式 - 林德熙)了解可以使用那些目标框架。新的 Microsoft.NET.Sdk 以不兼容的方式原生支持了 NuGet 包管理。也就是说我们可以在不修改 csproj 的情况之下通过 NuGet 包来扩展 csproj 的功能。而旧的格式需要在 csproj 文件的末尾添加如下代码才可以获得其中一个 NuGet 包功能的支持:不过好在 NuGet 4.x 以上版本在安装 NuGet 包时自动为我们在 csproj 中插入了以上代码。原文地址:https://walterlv.github.io/post/understand-the-csproj.html ©著作权归作者所有,转载或内容合作请联系作者 人面猴序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...沈念sama阅读 146,067评论 1赞 309死咒序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...沈念sama阅读 62,478评论 1赞 260救了他两次的神仙让他今天三更去死文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...开封第一讲书人阅读 97,028评论 0赞 215道士缉凶录:失踪的卖姜人 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...开封第一讲书人阅读 41,647评论 0赞 186港岛之恋(遗憾婚礼)正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...茶点故事阅读 49,531评论 1赞 263恶毒庶女顶嫁案:这布局不是一般人想出来的文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...开封第一讲书人阅读 39,131评论 1赞 182城市分裂传说那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...沈念sama阅读 30,705评论 2赞 279双鸳鸯连环套:你想象不到人心有多黑文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...开封第一讲书人阅读 29,477评论 0赞 174万荣杀人案实录序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...沈念sama阅读 32,842评论 0赞 218护林员之死正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...茶点故事阅读 29,556评论 2赞 223白月光启示录正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...茶点故事阅读 30,888评论 1赞 234活死人序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...沈念sama阅读 27,356评论 2赞 219日本核电站爆炸内幕正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...茶点故事阅读 31,824评论 3赞 214男人毒药:我在死后第九天来索命文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...开封第一讲书人阅读 25,713评论 0赞 9一桩弑父案,背后竟有这般阴谋文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...开封第一讲书人阅读 26,147评论 0赞 170情欲美人皮我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...沈念sama阅读 33,880评论 2赞 236代替公主和亲正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...茶点故事阅读 34,047评论 2赞 240推荐阅读更多精彩内容Spring CloudSpring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...卡卡罗2017阅读 134,023评论 18赞 139从零开始构建MSBuild C#项目文件本文参考自MSDN的一篇文章,从零开始创建MSBuild C#项目文件。 准备条件 一个好用的文本编辑器,例如At...乐百川阅读 2,754评论 1赞 2iOS 面试宝典 没有比这更全的了(持续更新)1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...欧辰_OSR阅读 28,946评论 8赞 265Jenkins ant build.xml文件详解(学习笔记六)ANT build.xml文件详解(一) Ant的概念 可能有些读者并不连接什么是Ant以及入可使用它,但只要使用...SkTj阅读 3,753评论 0赞 2我一直很迷你我一直很喜欢小爽。《演员的诞生》里的小爽让我看到了不一样的你。 之前微博,QQ看点上闹得很火。流量小花郑爽终于有人...飞驰的婷婷阅读 220评论 0赞 2评论0赞11赞2赞赞赏更
从头开始创建 MSBuild 项目文件 - MSBuild | Microsoft Learn
从头开始创建 MSBuild 项目文件 - MSBuild | Microsoft Learn
跳转至主内容
此浏览器不再受支持。
请升级到 Microsoft Edge 以使用最新的功能、安全更新和技术支持。
下载 Microsoft Edge
有关 Internet Explorer 和 Microsoft Edge 的详细信息
目录
退出焦点模式
使用英语阅读
保存
目录
使用英语阅读
保存
打印
电子邮件
目录
演练:从头开始创建 MSBuild 项目文件
项目
06/19/2023
11 个参与者
反馈
本文内容
面向 .NET Framework 的编程语言将使用 MSBuild 项目文件来介绍并控制应用程序生成过程。 使用 Visual Studio 创建 MSBuild 项目文件时,会自动将适当的 XML 添加到该文件。 但是,你可能会发现,了解 XML 的组织方式以及如何能够更改 XML 来控制生成将非常有用。
注意
如果想了解 MSBuild 如何独立于任何 SDK 工作的基础知识,本文是个不错的选择。 本文不涉及使用 SDK 生成(例如使用 dotnet build 或将 Sdk 属性添加到根项目元素)。 请参阅 .NET 项目 SDK。
有关为 C++ 项目创建项目文件的信息,请参阅 MSBuild (C++)。
此演练演示如何只使用文本编辑器以增量方式创建基本项目文件。 演练采用以下步骤:
扩展 PATH 环境变量。
创建最小的应用程序源文件。
创建最小的 MSBuild 项目文件。
使用项目文件生成应用程序。
添加属性以控制生成。
通过更改属性值来控制生成。
将目标添加到生成。
通过指定目标来控制生成。
以增量方式生成。
此演练演示如何在命令提示符下生成项目并检查结果。 有关 MSBuild 以及如何在命令提示符下运行 MSBuild 的详细信息,请参阅演练:使用 MSBuild。
要完成演练,必须安装 Visual Studio,因为其中包括演练所需的 MSBuild 和 C# 编译器。
扩展路径
必须先扩展 PATH 环境变量以包括全部所需工具,然后才能使用 MSBuild。 你可以使用“Visual Studio 开发人员命令提示”。 在 Windows 10 上,在 Windows 任务栏的搜索框中进行搜索。 要在普通命令提示符下或在脚本环境中设置环境,请在 Visual Studio 安装的 Common7/Tools 子文件夹中运行 VSDevCmd.bat 。
创建最小的应用程序
本部分演示如何使用文本编辑器创建最小的 C# 应用程序源文件。
在命令提示符下,浏览到要在其中创建应用程序的文件夹,例如,\My Documents\ 或 \Desktop\。
创建一个名为 \HelloWorld\ 的子文件夹并更改目录以进入其中。
在文本编辑器中,创建一个新文件 HelloWorld.cs,然后复制并粘贴以下代码:
using System;
class HelloWorld
{
static void Main()
{
#if DebugConfig
Console.WriteLine("WE ARE IN THE DEBUG CONFIGURATION");
#endif
Console.WriteLine("Hello, world!");
}
}
在命令提示符下,键入 csc helloworld.cs 来生成应用程序。
在命令提示符下,键入 helloworld 测试应用程序。
此时应显示“Hello, world!”消息。
测试可执行文件。
创建最小的 MSBuild 项目文件
既然有了最小的应用程序源文件,你就可以创建最小的项目文件来生成应用程序。 此项目文件包含以下元素:
必需的根 Project 节点。
用于包含项元素的 ItemGroup 节点。
引用应用程序源文件的项元素。
一个 Target 节点,用于包含生成应用程序所需的任务。
一个 Task 元素,用于启动 C# 编译器以生成应用程序。
创建最小的 MSBuild 项目文件
在文本编辑器中,创建一个新文件 HelloWorld.csproj 并输入以下代码:
此 ItemGroup 包含一个项元素 Compile 并将一个源文件指定为项。
添加一个 Target 节点,作为 Project 节点的子元素。 将该节点命名为 Build。
插入此 task 元素,作为 Target 节点的子元素:
保存此项目文件,并将其命名为“Helloworld.csproj”。
你的最小项目文件应类似于以下代码:
Build 目标中的任务按顺序执行。 在本例中,C# 编译器 Csc 任务是唯一的任务。 它需要编译一系列源文件,这一系列文件由 Compile 项的值指定。 Compile 项只引用一个源文件,即 Helloworld.cs。
注意
在项元素中,可以使用星号通配符 (*) 来引用文件扩展名为 .cs 的所有文件,如下所示:
生成应用程序
现在,为了生成应用程序,请使用刚刚创建的项目文件。
在命令提示符处,键入 msbuild helloworld.csproj -t:Build。
此操作将调用 C# 编译器来创建 Helloworld 应用程序,从而生成 Helloworld 项目文件的生成目标。
键入 helloworld 测试应用程序。
此时应显示“Hello, world!”消息。
注意
可以通过提高详细信息级别来查看有关生成的更多详细级别。 要将详细级别设置为“详细”,请在命令提示符下键入命令:
msbuild helloworld.csproj -t:Build -verbosity:detailed
添加生成属性
可以将生成属性添加到项目文件中,从而进一步控制生成。 现在添加以下属性:
一个 AssemblyName 属性,用于指定应用程序的名称。
一个 OutputPath 属性,用于指定要包含应用程序的文件夹。
添加生成属性
删除现有的应用程序可执行文件(稍后,你将添加一个 Clean 目标来处理旧输出文件的删除)。
在项目文件中,插入此 PropertyGroup 元素,置于起始 Project 元素的后面:
将此任务添加到 Build 目标,置于 Csc 任务的前面:
MakeDir 任务将创建一个由 OutputPath 属性命名的文件夹,前提是当前不存在具有该名称的文件夹。
将此 OutputAssembly 特性添加到 Csc 任务:
这将指示 C# 编译器生成由 AssemblyName 属性命名的程序集,并将其放在由 OutputPath 属性命名的文件夹中。
保存更改。
你的项目文件现在应类似于以下代码:
注意
在 OutputPath 元素中指定文件夹名称时,建议在文件夹名称的末尾添加反斜杠 (\) 路径分隔符,而不是将其添加到 Csc 任务的 OutputAssembly 属性中。 因此,
OutputAssembly="$(OutputPath)$(AssemblyName).exe" />
优于
OutputAssembly="$(OutputPath)\$(AssemblyName).exe" />
测试生成属性
现在即可使用项目文件来生成应用程序,在该项目文件中,你使用了生成属性来指定输出文件夹和应用程序名称。
在命令提示符处,键入 msbuild helloworld.csproj -t:Build。
这将创建“\Bin”文件夹,然后调用 C# 编译器创建 MSBuildSample 应用程序,并将其放在“\Bin”文件夹中。
要验证是否已创建“\Bin\”文件夹,以及该文件夹是否包含 MSBuildSample 应用程序,请键入“dir Bin”。
通过键入“Bin\MSBuildSample”运行可执行文件来测试应用程序。
此时应显示“Hello, world!”消息。
添加生成目标
接下来,向项目文件中另外添加两个目标,如下所示:
一个用于删除旧文件的 Clean 目标。
一个 Rebuild 目标,该目标使用 DependsOnTargets 特性,强制使 Clean 任务在 Build 任务之前运行。
既然有多个目标,就可以将 Build 目标设置为默认目标。
添加生成目标
在项目文件中添加以下两个目标,置于 Build 目标的后面:
Clean 目标调用 Delete 任务来删除应用程序。 在 Clean 目标和 Build 目标均已运行之前,Rebuild 目标不会运行。 尽管 Rebuild 目标没有任务,但它可使 Clean 目标在 Build 目标之前运行。
将此 DefaultTargets 特性添加到起始 Project 元素:
这会将 Build 目标设置为默认目标。
你的项目文件现在应类似于以下代码:
测试生成目标
可以执行新的生成目标来测试项目文件的以下功能:
生成默认生成。
在命令提示符下设置应用程序名称。
在生成其他应用程序之前删除应用程序。
删除应用程序,而不生成其他应用程序。
测试生成目标
在命令提示符处,键入msbuild helloworld.csproj -p:AssemblyName=Greetings。
由于未使用 -t 开关显式设置目标,因此 MSBuild 运行默认 Build 目标。 -p 开关替代 AssemblyName 属性,并为它指定新值 Greetings。 这将导致在“\Bin\”文件夹中创建一个新应用程序 Greetings.exe。
要验证“\Bin\”文件夹是否同时包含 MSBuildSample 应用程序和新的 Greetings 应用程序,请键入“dir Bin”。
测试 Greetings 应用程序(例如,在 Windows 上键入“Bin\Greetings”)。
此时应显示“Hello, world!”消息。
通过键入 msbuild helloworld.csproj -t:clean,删除 MSBuildSample 应用程序。
这将运行 Clean 任务,以删除具有默认 AssemblyName 属性值 MSBuildSample 的应用程序。
通过键入 msbuild helloworld.csproj -t:clean -p:AssemblyName=Greetings,删除 Greetings 应用程序。
这将运行 Clean 任务,以删除具有指定 AssemblyName 属性值 Greetings 的应用程序。
要验证“\Bin\”文件夹现在是否为空,请键入“dir Bin”。
键入 msbuild。
尽管未指定项目文件,但 MSBuild 会生成 helloworld.csproj 文件,因为当前文件夹中只有一个项目文件。 这将导致在“\Bin\”文件夹中创建 MSBuildSample 应用程序。
要验证“\Bin\”文件夹是否包含 MSBuildSample 应用程序,请键入“dir Bin”。
增量生成
可以指示 MSBuild 仅在目标所依赖的源文件或目标文件发生更改时才生成目标。 MSBuild 使用文件的时间戳来确定文件是否已更改。
以增量方式生成
在项目文件中,将以下特性添加到起始 Build 目标:
Inputs="@(Compile)" Outputs="$(OutputPath)$(AssemblyName).exe"
它指定 Build 目标依赖于 Compile 项组中指定的输入文件,并且输出目标为应用程序文件。
生成的 Build 目标应类似于以下代码:
在命令提示符处,键入 msbuild -v:d,以测试 Build 目标。
请记住,helloworld.csproj 是默认项目文件,并且 Build 为默认目标。
-v:d 开关是之前使用的 -verbosity:detailed 的缩写。
如果已生成输出,应显示以下行:
正在跳过目标“Build”,因为所有输出文件相对于输入文件而言都是最新的
MSBuild 将跳过 Build 目标,原因是自上次生成应用程序以来没有任何源文件发生更改。
C# 示例
下面的示例演示一个项目文件,该项目文件编译 C# 应用程序并记录包含输出文件名的消息。
代码
Sources = "@(CSFile)" OutputAssembly = "$(appname).exe">
Visual Basic 示例
下面的示例演示一个项目文件,该项目文件编译 Visual Basic 应用程序并记录包含输出文件名的消息。
代码
Sources = "@(VBFile)" OutputAssembly= "$(appname).exe">
后续步骤
Visual Studio 能够自动执行本演练中演示的大部分工作。 若要了解如何使用 Visual Studio 来创建、编辑、生成和测试 MSBuild 项目文件,请参阅演练:使用 MSBuild。
相关内容
MSBuild 概述
MSBuild 参考
其他资源
加州消费者隐私法案 (CCPA) 禁用图标
你的隐私选择
主题
亮
暗
高对比度
早期版本
博客
参与
隐私
使用条款
商标
© Microsoft 2024
其他资源
本文内容
加州消费者隐私法案 (CCPA) 禁用图标
你的隐私选择
主题
亮
暗
高对比度
早期版本
博客
参与
隐私
使用条款
商标
© Microsoft 2024
MSBuild 遇上 .NET Core 的 csproj 文件 | 思与行
MSBuild 遇上 .NET Core 的 csproj 文件 | 思与行
思与行
首页
标签
分类
归档
MSBuild 遇上 .NET Core 的 csproj 文件
发表于
2020-08-22
|
更新于
2020-11-05
|
分类于
MSBuild
本文详解 .NET Core 的 csproj 文件
在上一篇 MSBuild 入门 说到,如果通过 Visual Studio 2019 创建一个 Web项目 的时候,csproj 文件是这样子的:
1234567
.NET Core 的 csproj 文件变得如此不同的原因是:
MSBuild 15.0 引入了“项目 SDK”的概念
隐式包引用
因为隐式和默认值的原因,所以更改极大地简化了项目文件,但官方提供了如何像 MSBuild 一样查看整个项目
可以在命令行 CD 切换到的项目路径,也就是说该路径下有一个 .csproj 的文件,然后以下执行命令:
1dotnet msbuild -pp:fullproject.xml
则会在该目录下生成一个 fullproject.xml 文件,内容是把 .csproj 所以隐式和默认的内容完整的显示出来。
当 Sdk="Microsoft.NET.Sdk.Web",会隐式引用包 Microsoft.NETCore.App 与 Microsoft.AspNetCore.App
1234567
相当于:
123456789101112131415
如果将 Sdk="Microsoft.NET.Sdk.Web" 修改成 Sdk="Microsoft.NET.Sdk",那么则不会隐式引用 Microsoft.AspNetCore.App~
1234567
相当于:
1234567891011
如果将:
1234567
修改成:
1234567
那么在 Visual Studio 的 解决方案资源管理器,项目的 依赖项 的框架中的 Microsoft.AspNetCore.App 则会消失~
Sdk 属性的值有:
Microsoft.NET.Sdk 的 .NET Core SDK
Microsoft.NET.Sdk.Web 的 .NET Core Web SDK
Microsoft.NET.Sdk.Razor 的 .NET Core Razor 类库 SDK
Microsoft.NET.Sdk.Worker 的 .NET Core Worker Service(自 .NET Core 3.0 起)
Microsoft.NET.Sdk.WindowsDesktop 的 .NET Core WinForms 和 WPF(自 .NET Core 3.0 起)
目标框架名字对象 (TFM)
目标 Framework
最新稳定版本
netstandard2.1
.NET Standard
2.1
netcoreapp3.1
.NET Core
3.1
net48
.NET Framework
4.8
所有的值可以查看SDK 样式项目中的目标框架,想在 VS 中操作,可以查看 框架定位概述
在指定多个目标框架时,可有条件地为每个目标框架引用程序集。
123456789101112131415161718
对应的可以在库或应用中,编写条件代码以为每个目标框架编译:
12345678910111213public class MyClass{ static void Main() {#if NET40 Console.WriteLine("Target framework: .NET Framework 4.0");#elif NET45 Console.WriteLine("Target framework: .NET Framework 4.5");#else Console.WriteLine("Target framework: .NET Standard 1.4");#endif }}
参考资料MSBuild 如何生成项目.NET Core 的 csproj 格式的新增内容如何:使用 MSBuild 项目 SDK
觉得文章对您有帮助,请我喝瓶肥宅快乐水可好 (๑•̀ㅂ•́)و✧
打赏
微信支付
支付宝
本文作者: 阿彬~
本文链接:
https://iweixubin.github.io/posts/msbuild/dotnet-core-csproj/
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
免责声明:本媒体部分图片,版权归原作者所有。因条件限制,无法找到来源和作者未进行标注。
如果侵犯到您的权益,请与我联系删除
# MSBuild
# 编译
MSBuild 入门
MSBuild 遇上 Microsoft.AspNetCore.Http.csproj
文章目录
站点概览
阿彬~
苏格拉底粉
59
日志
19
分类
51
标签
GitHub
1. 参考资料
© 2018 – 2020
阿彬~
C# 编译器选项 | Microsoft Learn
C# 编译器选项 | Microsoft Learn
跳转至主内容
此浏览器不再受支持。
请升级到 Microsoft Edge 以使用最新的功能、安全更新和技术支持。
下载 Microsoft Edge
有关 Internet Explorer 和 Microsoft Edge 的详细信息
目录
退出焦点模式
使用英语阅读
保存
目录
使用英语阅读
保存
打印
电子邮件
目录
C# 编译器选项
项目
02/15/2023
11 个参与者
反馈
本文内容
本节介绍 C# 编译器解释的选项。 选项根据其控制的内容(例如语言功能、代码生成和输出)分组到不同的文章中。 使用目录来浏览它们。
如何设置选项
可以通过两种不同的方法设置 .NET 项目中的编译器选项:
在你的 *.csproj 文件中
可以 XML 格式为 *.csproj 文件中的任何编译器选项添加 MSBuild 属性。 属性名称与编译器选项相同。 用属性的值设置编译器选项的值。 例如,下面的项目文件段设置 LangVersion 属性。
有关项目文件中设置选项的详细信息,请参阅适用于 .NET SDK 项目的 MSBuild 属性一文。
使用 Visual Studio 属性页
Visual Studio 提供了属性页,可用于编辑生成属性。 若要了解有关详细信息,请参阅管理项目和解决方案属性 - Windows 或管理项目和解决方案属性 - Mac。
.NET Framework 项目
重要
本部分仅适用于 .NET Framework 项目。
除上述机制以外,还可以使用两种附加方法为 .NET Framework 项目设置编译器选项:
.NET Framework 项目的命令行参数:.NET Framework 项目使用 csc.exe 而不是 dotnet build 生成项目。 可以为 .NET Framework 项目指定 csc.exe 的命令行参数。
已编译的 ASP.NET 页面:.NET Framework 项目使用 web.config 文件的一部分来编译页面。 对于新的生成系统和 ASP.NET Core 项目,将从项目文件中设置选项。
某些编译器选项的单词从 csc.exe 和 .NET Framework 项目更改为新的 MSBuild 系统。 本部分使用的是新语法。 每个页面顶部同时列出了这两个版本。 对于 csc.exe,所有参数都会在选项和冒号后列出。 例如,-doc 选项将为:
-doc:DocFile.xml
通过在命令提示符处键入 C# 编译器的可执行文件名称 (csc.exe),可调用该编译器。
对于 .NET Framework 项目,还可以从命令行运行 csc.exe。 每个编译器选项均有两种形式: -option 和 /option。 在 .NET Framework Web 项目中,在 web.config 文件中指定用于编译代码隐藏的选项。 有关详细信息,请参阅
如果使用“Visual Studio 开发人员命令提示”窗口,系统将设置所有必需的环境变量。 有关如何访问此工具的信息,请参阅 Visual Studio 开发人员命令提示。
csc.exe 可执行文件通常位于 Windows 目录下的 Microsoft.NET\Framework\
其他资源
加州消费者隐私法案 (CCPA) 禁用图标
你的隐私选择
主题
亮
暗
高对比度
早期版本
博客
参与
隐私
使用条款
商标
© Microsoft 2024
其他资源
本文内容
加州消费者隐私法案 (CCPA) 禁用图标
你的隐私选择
主题
亮
暗
高对比度
早期版本
博客
参与
隐私
使用条款
商标
© Microsoft 2024
常用的 MSBuild 项目属性 - MSBuild | Microsoft Learn
常用的 MSBuild 项目属性 - MSBuild | Microsoft Learn
跳转至主内容
此浏览器不再受支持。
请升级到 Microsoft Edge 以使用最新的功能、安全更新和技术支持。
下载 Microsoft Edge
有关 Internet Explorer 和 Microsoft Edge 的详细信息
目录
退出焦点模式
语言
使用英语阅读
保存
目录
使用英语阅读
保存
打印
电子邮件
目录
常用的 MSBuild 项目属性
项目
06/06/2023
19 个参与者
反馈
本文内容
下表列出了在 Visual Studio 项目文件中定义的或者在 MSBuild 提供的 .targets 文件中包括的经常使用的属性。
Visual Studio 中的项目文件(.csproj、.vbproj、vcxproj 等)包含你使用 IDE 生成项目时运行的 MSBuild XML 代码 。 项目通常会导入一个或多个 .targets 文件以定义它们的生成进程。 有关详细信息,请参阅 MSBuild .Targets 文件。
在设置属性值时,请记住,可以在许多导入的文件中设置、重置或使用公共属性。 因此,设置属性的位置非常重要,可以在项目文件、Directory.Build.props 或其他导入文件中进行设置。 如果要在某个位置设置属性但未获得预期结果,请考虑在项目导入的所有文件中更改或使用该属性的位置和方式,包括在使用 Sdk 特性时隐式添加的导入。 请参阅选择将属性添加到 .props 文件或 .targets 文件。 预处理可帮助完成此操作(请参阅 MSBuild 命令行参考中的 /preprocess 或 /pp 命令行选项)。
通用属性和参数的列表
属性或参数名
项目类型
描述
AdditionalLibPaths
.NET
指定其他文件夹,编译器将在这些文件夹中查找引用程序集。
AddModules
.NET
使编译器让指定文件中的所有类型信息可供正在编译的项目使用。 此属性等效于 /addModules 编译器开关。
ALToolPath
.NET
AL.exe 的路径。 此属性将替代 AL.exe 的当前版本,从而允许使用其他版本。
ApplicationIcon
.NET
要传递给编译器以作为 Win32 图标嵌入的 .ico 图标文件。 该属性等效于 /win32icon 编译器开关。
ApplicationManifest
全部
指定用于生成外部用户帐户控制 (UAC) 清单信息的文件的路径。 仅适用于面向 Windows Vista 的 Visual Studio 项目。 在大多数情况,该清单是嵌入的。 但如果使用免注册的 COM 或 ClickOnce 部署,则该清单可以是随应用程序程序集一起安装的外部文件。 有关详细信息,请参阅本文中的 NoWin32Manifest 属性。
AssemblyOriginatorKeyFile
.NET
指定用于为程序集(.snk 或 .pfx)签名并传递给 ResolveKeySource 任务的文件,以便生成用于对程序集签名的实际密钥。
AssemblySearchPaths
.NET
要在生成时引用程序集解析期间搜索的位置列表。 路径在此列表中的出现顺序是有含义的,因为先列出的路径优先于后列出的条目。
AssemblyName
.NET
生成项目后的最终输出程序集的名称。
属性或参数名
项目类型
说明
BaseAddress
.NET
指定主输出程序集的基址。 此属性等效于 /baseaddress 编译器开关。
BaseIntermediateOutputPath
全部
在其中创建所有配置特定的中间输出文件夹的顶级文件夹。 默认值为 obj\。 下面的代码是一个示例:
BaseOutputPath
全部
指定输出文件的基路径。 如果已设置,MSBuild 将使用 OutputPath = $(BaseOutputPath)\$(Configuration)\。 示例语法:
BuildInParallel
全部
一个布尔值,指示在使用多处理器 MSBuild 时并行生成还是清理项目引用。 默认值为 true,该值表示如果系统有多个核心或处理器,则将并行生成项目。
BuildProjectReferences
全部
一个布尔值,指示是否由 MSBuild 生成项目引用。 如果在 Visual Studio 集成开发环境 (IDE) 中生成项目,则自动设置为 false;否则设置为 true。 可以在命令行上指定 -p:BuildProjectReferences=false 以避免检查引用的项目是否为最新。
属性或参数名
项目类型
说明
CleanFile
全部
将用作“清理缓存”的文件的名称。清理缓存是要在清理操作期间删除的已生成文件的列表。 该文件由生成过程放在中间输出路径中。 此属性只指定没有路径信息的文件名。
CodePage
.NET
指定要用于编译中所有源代码文件的代码页。 此属性等效于 /codepage 编译器开关。
CompilerResponseFile
.NET
可以传递给编译器任务的可选响应文件。
Configuration
全部
正在生成的配置,通常为 Debug 或 Release,但可以在解决方案和项目级别进行配置。
CscToolPath
C#
C# 编译器 csc.exe 的路径。
CustomAfterMicrosoftCommonTargets
全部
要在公用目标导入后自动导入的项目文件或目标文件的名称。
CustomBeforeMicrosoftCommonTargets
全部
要在公用目标导入前自动导入的项目文件或目标文件的名称。
属性或参数名
项目类型
说明
DebugSymbols
全部
一个布尔值,指示是否由生成来生成符号。 在命令行中设置 -p:DebugSymbols=false 会禁止生成程序数据库 (.pdb) 符号文件。
DebugType
全部
定义要生成的调试信息的级别。 有效值为“full”、“pdbonly”、“portable”、“embedded”和“none”。
DefineConstants
.NET
定义条件编译器常数。 符号/值对是使用从属语言语法指定的,并且彼此之间用分号分隔: C#:symbol1; symbol2 Visual Basic:symbol1 = value1, symbol2 = value2 该属性等效于 /define 编译器开关。
DefineDebug
全部
一个布尔值,指示是否定义 DEBUG 常量。
DefineTrace
全部
一个布尔值,指示是否定义 TRACE 常量。
DelaySign
.NET
一个布尔值,指示是否对程序集进行延迟签名,而不对其进行完整签名。
Deterministic
.NET
一个布尔值,指示编译器是否为相同的输入生成相同的程序集。 此参数对应于编译器的 /deterministic 开关。
DirectoryBuildPropsPath
全部
指定 Directory.Build.props 文件的路径;如果已定义,则此属性将替代默认搜索算法。 请参阅自定义生成。
DirectoryBuildTargetsPath
全部
指定 Directory.Build.targets 文件的路径;如果已定义,则此属性将替代默认搜索算法。 请参阅自定义生成。
DisableFastUpToDateCheck
全部
一个只适用于 Visual Studio 的布尔值。 Visual Studio 生成管理器使用名为 FastUpToDateCheck 的进程来确定项目是否必须重新生成才能保持最新。 与使用 MSBuild 相比,此进程能更快地确定这一点。 通过将 DisableFastUpToDateCheck 属性设置为 true,可以跳过 Visual Studio 生成管理器,并强制生成管理器使用 MSBuild 来确定项目是否为最新版本。
DocumentationFile
.NET
作为 XML 文档文件生成的文件的名称。 此名称只包含文件名,不包含路径信息。
属性或参数名
项目类型
说明
ErrorReport
.NET
指定编译器任务报告内部编译器错误的方式。 有效值为“prompt”、“send”或“none”。此属性等效于 /errorreport 编译器开关。
ExcludeDeploymentUrl
.NET
GenerateDeploymentManifest 任务会在项目文件包含下列任何元素时向部署清单中添加 deploymentProvider 标记: - UpdateUrl- InstallUrl- PublishUrl 不过,使用 ExcludeDeploymentUrl,可以防止 deploymentProvider 标记添加到部署清单,即使指定了任何上述 URL。 为此,请将以下属性添加到项目文件:
FileAlignment
.NET
指定输出文件各部分的对齐位置,以字节为单位。 有效值为 512、1024、2048、4096、8192。 此属性等效于 /filealignment 编译器开关。
FrameworkPathOverride
Visual Basic
指定 mscorlib.dll 和 microsoft.visualbasic.dll 的位置 。 此参数等效于 vbc.exe 编译器的 /sdkpath 开关。
GenerateDocumentation
.NET
一个布尔型参数,指示是否由生成来生成文档。 如果设置为 true,生成过程将生成文档信息,并将此信息与生成任务所创建的可执行文件或库的名称一同放置在 .xml 文件中。
GenerateFullPaths
C#
使用 -fullpaths 编译器选项为输出中的文件名生成完整路径。
GenerateSerializationAssemblies
.NET
指示是否应通过 SGen.exe 生成 XML 序列化程序集,它可以设置为开、自动或关。 此属性用于仅面向 .NET Framework 的程序集。 要生成 .NET Standard 或 .NET Core 程序集的 XML 序列化程序集,请参考 Microsoft.XmlSerializer.Generator NuGet 包。
属性或参数名
项目类型
说明
ImportDirectoryBuildProps
全部
一个布尔值,指示是否导入 Directory.Build.props 文件。 请参阅自定义生成。
ImportDirectoryBuildTargets
全部
一个布尔值,指示是否导入 Directory.Build.targets 文件。 请参阅自定义生成。
IntermediateOutputPath
全部
如果未指定路径,则为从 BaseIntermediateOutputPath 派生的完整中间输出路径。 例如 obj\debug\。
KeyContainerName
全部
强名称密钥容器的名称。
KeyOriginatorFile
全部
强名称密钥文件的名称。
ModuleAssemblyName
.NET
要将编译好的模块并入其中的程序集的名称。 该属性等效于 /moduleassemblyname 编译器开关。
MSBuildProjectExtensionsPath
全部
指定项目扩展所在的路径。 默认情况下,该路径与 BaseIntermediateOutputPath 具有相同值。
MSBuildTreatWarningsAsErrors
全部
一个布尔值,告知 MSBuild 将所有警告视为错误,除非它们被禁止显示。
MSBuildWarningsAsErrors
全部
指定将被视为错误的警告代码列表。 用分号分隔多个警告。 如果使用 .NET SDK 属性 WarningsAsErrors,则 MSBuildWarningsAsErrors 将默认为 WarningsAsErrors 的值。
MSBuildWarningsAsMessages
全部
通过将警告代码视为低重要性消息来指定要禁止显示的警告代码列表。 用分号分隔多个警告。 请注意,使用此属性无法禁止显示 MSBuild 发出的某些警告;要将其禁止显示,请使用命令行开关 -warnAsMessage。 如果使用 .NET SDK 属性 NoWarn,则 MSBuildWarningsAsMessages 将默认为 NoWarn 的值。
属性或参数名
项目类型
说明
NoLogo
全部
一个指示是否关闭编译器徽标的布尔值。 此属性等效于 /nologo 编译器开关。
NoStdLib
.NET
一个指示是否避免引用标准库 (mscorlib.dll) 的布尔值。 默认值为 false。
NoVBRuntimeReference
Visual Basic
一个布尔值,指示是否应包括 Visual Basic 运行时 (Microsoft.VisualBasic.dll) 作为项目中的引用。
NoWarn
.NET
禁止显示指定的警告。 只有警告标识符的数值部分是必须指定的。 多个警告之间用分号分隔。 此参数对应于编译器的 /nowarn 开关。
NoWin32Manifest
.NET
一个布尔值,指示是否将用户帐户控制 (UAC) 清单信息嵌入在应用程序的可执行文件中。 仅适用于面向 Windows Vista 的 Visual Studio 项目。 在使用 ClickOnce 和免注册的 COM 部署的项目中,将忽略此元素。 False(默认值)指示是否将用户帐户控制 (UAC) 清单信息嵌入在应用程序的可执行文件中。 True 指定不嵌入 UAC 清单信息。 此属性仅适用于面向 Windows Vista 的 Visual Studio 项目。 在使用 ClickOnce 和免注册的 COM 部署的项目中,将忽略此属性。 只有在不需要 Visual Studio 在应用程序的可执行文件中嵌入任何清单信息时,才应该添加 NoWin32Manifest;此过程称为“虚拟化”。 若要使用虚拟化,请按照下列方式设置
Optimize
.NET
一个布尔值,在设置为 true 时,允许进行编译器优化。 此属性等效于 /optimize 编译器开关。
OptionCompare
VisualBasic
指定如何进行字符串比较。 有效值为“binary”或“text”。此属性等效于 vbc.exe 的 /optioncompare 编译器开关。
OptionExplicit
Visual Basic
一个布尔值,设置为 true 时,要求在源代码中显式声明变量。 此属性等效于 /optionexplicit 编译器开关。
OptionInfer
Visual Basic
一个布尔值,设置为 true 时,允许进行变量的类型推理。 此属性等效于 /optioninfer 编译器开关。
OptionStrict
Visual Basic
一个布尔值,设置为 true 时,将使得生成任务强制使用严格类型语义来限制隐式类型转换。 此属性等效于 vbc.exe 编译器的 /optionstrict 开关。
OutDir
全部
指示项目或解决方案的最终输出位置。 在生成解决方案时,可以使用 OutDir 将多个项目输出收集到一个位置。 此外,OutDir 包含在用于解析引用的 AssemblySearchPaths 中。 例如 bin\Debug。
OutputPath
全部
相对于项目目录,例如 bin\Debug 或非 AnyCPU 版本中的 bin\Debug\$(Platform),指定输出目录的路径。
OutputType
全部
指定输出文件的文件格式。 此参数可以具有下列值之一: - Library。 创建一个代码库。 (默认值)。- Exe。 创建控制台应用程序。- Module。 创建一个模块。- Winexe。 创建一个基于 Windows 的程序。 对于 C# 和 Visual Basic,此属性等效于 /target 开关。 输出类型可以通过推理自动重写。 请参阅 对于 WPF 和 WinForms 应用,OutputType 设置为 WinExe。 通过将 DisableWinExeOutputInference 设置为 true 来禁用推理。
OverwriteReadOnlyFiles
全部
一个布尔值,指示要让生成覆盖只读文件还是触发错误。
属性或参数名
项目类型
说明
PathMap
.NET
指定如何将物理路径映射到编译器输出的源路径名称。 此属性等效于编译器的 /pathmap 开关。
PdbFile
.NET
正在发出的 .pdb 文件的文件名。 此属性等效于 csc.exe 编译器的 /pdb 开关。
Platform
全部
针对其进行生成操作的操作系统。 .NET Framework 生成示例包括“任何 CPU”、“x86”和“x64”。
ProcessorArchitecture
.NET
解析程序集引用时使用的处理器架构。 有效值为“msil”、“x86”、“amd64”或“ia64”。
ProduceOnlyReferenceAssembly
.NET
布尔值,指示编译器仅发出引用程序集,而不是已编译代码。 不能与 ProduceReferenceAssembly 一起使用。 此属性对应于 vbc.exe 和 csc.exe 编译器的 /refonly 开关 。
ProduceReferenceAssembly
.NET
一个布尔值,设置为 true 时,可为当前程序集生成引用程序集。 使用此功能时,Deterministic 应为 true。 此属性对应于 vbc.exe 和 csc.exe 编译器的 /refout 开关 。
RegisterAssemblyMSBuildArchitecture
仅限 Windows
指定注册托管 DLL 的默认体系结构。 此属性很有用,因为 COM 使用 Windows 注册表将注册存储在特定于体系结构的 Hive 中。 例如,在 Windows 系统上,AnyCPU 托管程序集可以在 64 位 Hive 和/或 32 位 (WoW) Hive 中注册其类型,并且生成将使用此属性来确定要使用的特定于体系结构的注册表 Hive。 有效值包括“x86”、“x64”和“ARM64”。
RegisterForCOMInterop
仅限 Windows
指示托管应用程序将公开 COM 对象(COM 可调用包装器)。 请参阅“生成”页面 - “输出”部分。 此设置仅影响正在生成相应项目的计算机。 如果要部署到其他计算机,请调用 regasm.exe 以在目标计算机上注册程序集。
RemoveIntegerChecks
Visual Basic
一个布尔值,指示是否禁用整数溢出错误检查。 默认值为 false。 此属性等效于 vbc.exe 编译器的 /removeintchecks 开关。
RootNamespace
全部
在命名嵌入资源时要使用的根命名空间。 此命名空间属于嵌入资源清单名称的一部分。
属性或参数名
项目类型
说明
Satellite_AlgorithmId
.NET
在创建附属程序集时要使用的 AL.exe 哈希算法的 ID。
Satellite_BaseAddress
.NET
在使用 CreateSatelliteAssemblies 目标生成特定于区域性的附属程序集时要使用的基址。
Satellite_CompanyName
.NET
要在附属程序集生成期间传入 AL.exe 的公司名称。
Satellite_Configuration
.NET
要在附属程序集生成期间传入 AL.exe 的配置名称。
Satellite_Description
.NET
要在附属程序集生成期间传入 AL.exe 的说明文本。
Satellite_EvidenceFile
.NET
在具有资源名称“Security.Evidence”的附属程序集中嵌入指定文件。
Satellite_FileVersion
.NET
为附属程序集中的“文件版本”字段指定字符串。
Satellite_Flags
.NET
指定附属程序集中“标志”字段的值。
Satellite_GenerateFullPaths
.NET
使生成任务对错误消息中报告的所有文件使用绝对路径。
Satellite_LinkResource
.NET
将指定的资源文件链接至某个附属程序集。
Satellite_MainEntryPoint
.NET
指定方法的完全限定名称(即 class.method),以用作在附属程序集生成期间将模块转换为可执行文件时的入口点。
Satellite_ProductName
.NET
为附属程序集中的“产品”字段指定字符串。
Satellite_ProductVersion
.NET
为附属程序集中的“ProductVersion”字段指定字符串。
Satellite_TargetType
.NET
将附属程序集输出文件的文件格式指定为“library”、“exe”或“win”。默认值为“library”。
Satellite_Title
.NET
为附属程序集中的“标题”字段指定字符串。
Satellite_Trademark
.NET
为附属程序集中的“商标”字段指定字符串。
Satellite_Version
.NET
指定附属程序集的版本信息。
Satellite_Win32Icon
.NET
在附属程序集中插入一个 .ico 图标文件。
Satellite_Win32Resource
.NET
在附属程序集中插入一个 Win32 资源(.res 文件)。
SGenToolPath
.NET
一个可选的工具路径,指示在当前版本的 SGen.exe 被重写时可以获得 SGen.exe 的位置 。
属性或参数名
项目类型
说明
SGenUseProxyTypes
.NET
一个布尔值,指示是否应由 SGen.exe 生成代理类型。 这仅适用于 GenerateSerializationAssemblies 设置为开的情况。 SGen 目标使用此属性来设置 UseProxyTypes 标志。 此属性默认为 true,并且没有可以更改此属性的 UI。 若要生成非 webservice 类型的序列化程序集,请在导入 Microsoft.Common.Targets 或 C#/VB.targets 之前将此属性添加到项目文件并将其设为 false 。
SkipInvalidConfigurations
全部
等于 true 时,会生成对无效平台和配置组合的警告,但不会让生成操作失败;等于 false 或未定义(默认值)时,会生成错误。
StartupObject
.NET
指定包含 Main 方法或 Sub Main 过程的类或模块。 此属性等效于 /main 编译器开关。
SubsystemVersion
.NET
指定生成的可执行文件可以使用的子系统的最低版本。 此属性等效于 /subsystemversion 编译器开关。 有关此属性的默认值的信息,请参阅 /subsystemversion (Visual Basic) 或 /subsystemversion(C# 编译器选项)。
TargetCompactFramework
.NET
运行你所生成的应用程序所需要的 .NET Compact Framework 的版本。 通过指定此属性,你可以引用否则将无法引用的某些 Framework 程序集。
TargetFrameworkVersion
.NET
运行你所生成的应用程序所需要的 .NET Framework 的版本。 通过指定此属性,你可以引用否则将无法引用的某些 Framework 程序集。
TreatWarningsAsErrors
.NET
一个布尔型参数,如果设置为 true,则会导致将所有警告都视为错误。 此参数等效于 /nowarn 编译器开关。
UseCommonOutputDirectory
.NET
想要解决方案中的所有生成输出使用同一输出目录时,可设为 true 的布尔属性。 如果为 true,则引用项目的输出不会复制到使用这些依赖项的项目中,就像通常情况下此设置为 false 时一样。 将此参数设置为 true 不会更改任何项目的实际输出目录;对于每个需要输出目录的项目,仍需将其设置为所需的公共输出目录。
UseHostCompilerIfAvailable
.NET
一个布尔型参数,如果设置为 true,则会使得生成任务使用进程内编译器对象(如果可用)。 此参数仅供 Visual Studio 使用。
Utf8Output
.NET
一个布尔型参数,如果设置为 true,则使用 UTF-8 编码记录编译器输出。 此参数等效于 /utf8Output 编译器开关。
属性或参数名
项目类型
说明
VbcToolPath
Visual Basic
一个可选路径,在当前版本的 vbc.exe 被重写时它可以指示 vbc.exe 的另一个位置 。
VbcVerbosity
Visual Basic
指定 Visual Basic 编译器输出的详细程度。 有效值为“Quiet”、“Normal”(默认值)或“Verbose”。
VisualStudioVersion
全部
指定运行此项目应考虑使用的 Visual Studio 的版本。 如果未指定此属性,MSBuild 会将其设置为 {VisualStudioMajorVersion}.0 的默认值;例如,对于所有版本的 Visual Studio 2022,它将是 17.0。 此属性在多种项目类型中用于指定要生成的目标组。 如果将某个项目的 ToolsVersion 设置为 4.0 或更高版本,则 VisualStudioVersion 将用于指定要使用的子工具集。 有关详细信息,请参阅工具集 (ToolsVersion)。
WarningsAsErrors
.NET
指定将被视为错误的警告的列表。 此参数等效于 /warnaserror 编译器开关。
WarningLevel
全部
指定要传递给编译器的警告等级,用于编译器发出的警告。 此设置不影响没有级别指定的 MSBuild 警告。 请参阅 C# 编译器文档中的警告等级和 C++ 编译器文档中的 /W(警告等级)。
WarningsNotAsErrors
.NET
指定不被视为错误的警告的列表。 此参数等效于 /warnaserror 编译器开关。
Win32Manifest
.NET
应嵌入最终程序集中的清单文件的名称。 此参数等效于 /win32Manifest 编译器开关。
Win32Resource
.NET
要嵌入最终程序集中的 Win32 资源的文件名。 此参数等效于 /win32resource 编译器开关。
框架属性中记录了特定于 .NET SDK 项目的属性,例如 TargetFramework。
请参阅
常用的 MSBuild 项目项
通用 MSBuild 项元数据
MSBuild 保留属性和已知属性
.NET SDK 项目的 MSBuild 引用
其他资源
加州消费者隐私法案 (CCPA) 禁用图标
你的隐私选择
主题
亮
暗
高对比度
早期版本
博客
参与
隐私
使用条款
商标
© Microsoft 2024
其他资源
本文内容
加州消费者隐私法案 (CCPA) 禁用图标
你的隐私选择
主题
亮
暗
高对比度
早期版本
博客
参与
隐私
使用条款
商标
© Microsoft 2024