imtoken网站|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的编程艺术微软全栈工程师,不定期分享各类技术和
.csproj 文件_csproj是什么文件-CSDN博客
>.csproj 文件_csproj是什么文件-CSDN博客
.csproj 文件
最新推荐文章于 2023-07-21 21:10:44 发布
RayRings
最新推荐文章于 2023-07-21 21:10:44 发布
阅读量1.5w
收藏
49
点赞数
8
分类专栏:
C#
文章标签:
C#
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_37805255/article/details/100104202
版权
C#
专栏收录该内容
6 篇文章
0 订阅
订阅专栏
.csproj 文件
.csproj,是C#项目文件的扩展名,它是“C Sharp Project”的缩写。.net开发环境中建立项目时,会产生.csproj文件,这是C#的工程文件,其中记录了与工程有关的相关信息,例如包含的文件,程序的版本,所生成的文件的类型和位置信息等。
【作用】
.csproj究竟是做什么用的?它是给开发工具用的,例如我们再熟悉不过的Visual Studio,以及大家可能没有接触过的MSBuild.exe。
Visual Studio会根据csproj里的XML定义来管理项目文件以及相关其他一些种类非常丰富的数据及操作,MSBuild也会根据csproj文件来得知编译这个项目需要有哪些依赖,默认输出路径,Pre-Build和Post-Build需要哪些操作等。
Visual Studio和MSBuild都是开发工具,这就是csproj存在的唯一意义:为“开发工具”提供信息。而到了运行环境中,根本不会有人关心所谓的csproj文件——也就是“程序是从哪里来的”。
【各个部件的作用】
PropertyGroup
PropertyGrouph是用来存放属性的地方,这与它的名字非常契合。
在这里写属性就像在代码中定义属性或变量一样,只要写了,就会生成一个指定名称的属性。
比如,我们写:
那么,就会生成一个 Foo 属性,值为字符串 watermelon is a fruit。至于这个属性有什么用,那就不归这里管了。
PropertyGroup可以定义很多个,里面都可以同等地放属性。至于为什么会定义多个,原因无外乎有两个:
增加可读性 —— 将一组相关的属性放在一起,便于阅读和理解意图;便于加条件 —— 有的属性在 Debug 和 Release 下不一样(例如条件编译符 DefineConstants)。
ItemGroup
ItemGroup是用来指定集合的地方。
集合里面一些常见的项:
Reference:引用某个程序集PackageReference:引用某个NuGet包ProjectReference:引用某个项目Compile:常规的 C# 编译None:执行一些通用的操作(或者只是为了在 Visual Studio 列表中能够有一个显示)Folder:一个空的文件夹
ItemGroup 也可以放很多组,同样是为了提升可读性或者增加条件。
Import
Import是为了导入属性(props)和Targets(后面会具体说Targets)。
被我们 Import 进来的那些文件,可以用两种扩展名表示,一种是用来定义属性,为 .props;另一种用来定义行为,为 .targets。这两种文件除了含义不同以外,内容的格式都是完全一样的 —— 即 csproj 文件格式。
虽然 csproj 文件中可以完全实现引入的 props 文件的功能,但为了在多个项目中使用,一处更新,到处生效,因此选择单独用 props 文件来存放。
Target
一般来说, Target 节点写在 csproj 文件的末尾,但这个并不是强制的。Targets 是一种非常强大的功能扩展方式,支持 msbuild 预定义的一些指令,支持命令行,甚至支持使用 C# 直接编写(当然编译成 dll 会更方便些),还支持这些的排列组合和顺序安排。而我们实质上的编译过程便全部由这些 Targets 来完成。甚至可以说,编译过程就是靠这些 Target 的组合来完成的。
Project
所有的 csproj 文件都是以 Project 节点为根节点。
下面列出新旧两款 csproj 文件格式的差异:
其中,在各部件中,白色代表必须,灰色代表可选;而更接近背景色的灰色代表一般情况下都是不需要的。
可以看出,新格式的最大好处之一就是简洁。而这一优势,靠的就是 Project 节点,新格式中的 Project 节点有 sdk 属性 —— 所谓 sdk,其实是一大波 .targets 文件的集合。它帮我们导入了公共的属性、公共的编译任务,还帮我们自动将项目文件夹下所有的 **\*.cs 文件都作为 ItemGroup 的项引入进来。
【 .sln 和 .csproj 的区别】
1. .sln:即 solution,解决方案
.csproj:即 C sharp project,C# 项目
2. 解决方案是项目的集合,项目是文件的集合;一个 sln 中可以包含多个 csproj。一个 csproj 可以包含多个文件; csproj 可以作为单独的项目运行,也可以在 sln 中添加 csproj 统一管理。
3. sln 和 csproj 都可以双击运行,如果解决方案中只有一个项目,那么两个方式是没有区别的;但是如果一个解决方案中包含多个项目, sln 会加载该解决方案中所有的项目,而 csproj 只会加载当前项目。
4. 关于 sln 和 csproj 的几个问题
(1)C#、.net 中,.sln 文件可以删掉重新生成吗?
.sln 是项目文件,删除后项目的一些设置会无法恢复,因为解决方案里面可能有关于这个项目文件的很多信息,所以一般不建议删除重建;但一般也没有太大的问题,用VS直接打开 .csproj 工程文件,会自动建上 sln 的。
(2)下载的 ASP.net 源码没有.sln 或 .csproj 文件如何使用?
从 Visual Studio IDE 的菜单 "文件" --> "打开" --> "网站" ,然后从右边的目录中选择要打开的网站目录,不需要有 .sln 文件就可以打开网站并调试运行。如果是 WebSite 模式那么是不需要 .sln 文件的,可以通过 File -> WebSite -> OpenWebSite 打开。如果不是 WebSite 模式,那么可以自己建立一个空项目,然后把文件 Copy 进去即可。
参考链接:https://blog.csdn.net/han_better/article/details/64140875
优惠劵
RayRings
关注
关注
8
点赞
踩
49
收藏
觉得还不错?
一键收藏
知道了
1
评论
.csproj 文件
.csproj 文件.csproj,是C#项目文件的扩展名,它是“C Sharp Project”的缩写。.net开发环境中建立项目时,会产生.csproj文件,这是C#的工程文件,其中记录了与工程有关的相关信息,例如包含的文件,程序的版本,所生成的文件的类型和位置信息等。【作用】.csproj究竟是做什么用的?它是给开发工具用的,例如我们再熟悉不过的Visual Studio,以...
复制链接
扫一扫
专栏目录
API_TEST.csproj.uesr
10-26
C#2416GPIO的项目文件,想要看的可借鉴借鉴
csproj 文件、sln文件的简单介绍。
weixin_30740581的博客
01-15
522
1.csproj文件:
.net 开发环境中建立项目时,会产生 .csproj 文件,这是C#的工程文件,其中记录了与工程有关的相关信息,例如包含的文件,程序的版本,所生成的文件的类型和位置的信息等。Visual Studio会根据csproj里的XML定义来管理项目文件以及相关其他一些种类非常丰富的数据及操作。为“开发环境”提供信息。到了运行环境中,iis根本不会关心所谓的csproj文件。 ...
1 条评论
您还未登录,请先
登录
后发表或查看评论
无聊的CSPROJ 文件,很无聊
dennydaniel的专栏
05-28
1387
http://schemas.microsoft.com/developer/msbuild/2003"> Debug AnyCPU 8.0.50727 2.0 {A626B36B-DA06-4DB5-8C00-BB7A52CB2AD8} WinExe Properties ReadCardv1 ReadCardv1 true
ProjectSync:这个基本的控制台应用程序使您的 *.csproj 文件与文件系统更改保持同步,使其在不专门使用 Visual Studio 进行开发的团队中工作时非常有用
07-01
项目同步
这个基本的控制台应用程序使您的 csproj 文件与文件系统更改保持同步,这在不专门使用 Visual Studio 进行开发的团队中工作时非常有用。
它目前支持单个命令行参数——要观察的工作目录。
它支持大量配置选项,所有选项都有“合理”的默认值,可以在 program.cs 的顶部看到
git提交数据教程
11-01
团队开发常用的git工具教程,这里提供的是上传文件教程的其中之一。
IDE(6)——VS系列(6)——csproj工程文件
qq_34573534的博客
06-10
1697
csproj工程文件
这里面,csproj是我们最常见的核心文件,CSharp Project,它是用于构建这个项目的工程文件。
csproj是基于xml格式的MSBuild项目文件,其仍然是文本文件,可以打开并修改定义了的工程构造的属性,比如选择性的添加或删除或修改包含在项目中的文件或引用、修改项目版本、将其转换为其它类型项目等。
MSBuild是微软定义的一个用于生成应用程序的平台(Mi...
理解 C# 项目 csproj 文件格式的本质和编译流程
oper1000的博客
01-27
927
写了这么多个 C# 项目,是否对项目文件 csproj 有一些了解呢?Visual Studio 是怎么让 csproj 中的内容正确显示出来的呢?更深入的,我能够自己扩展 csproj 的功能吗?
本文将直接从 csproj 文件格式的本质来看以上这些问题。
csproj文件常用设置及C#注释常用写法
博客
06-29
774
csproj文件常用设置及C#注释常用写法
(转)Visual Studio中.sln文件和.csproj文件的区别
逝不等琴生的博客
03-11
1807
介绍
sln:solusion 解决方案
csproj:c sharp project C#项目
区别
1.解决方案是项目的集合,项目是文件的集合;一个sln中可以包含多个csproj。一个csproj可以包含多个文件;csproj可以作为单独的项目运行,也可以在sln中添加csproj统一管理。
2.sln和csproj都可以双击运行,如果解决方案中只有一个项目那么两个方式是没有区别的...
【CSharp】关于xxx.csproj文件的理解
jn10010537的博客
07-21
592
Visual Studio会根据csproj里的内容来定义来管理项目文件以及相关其他一些种类非常丰富的数据及操作。.csproj文件记录了与工程有关的相关信息,例如包含的文件,程序的版本,所生成的文件的类型和位置信息等。在.NET框架的开发环境中建立项目时,会产生.csproj文件,这是C#的项目工程文件。csproj的全称是C Sharp Project的缩写,是C#项目文件的扩展名。上面的iRayBase.csproj 文件后缀是 .csproj。在示例代码里,遇到.csproj 文件。
vscode-csproj:Visual Studio Code扩展,使您的csproj文件保持最新
05-16
VS Code .csproj扩展
此扩展名将帮助您在使用VS Code时使csproj文件保持同步。 如果您在同时使用VS Code和Visual Studio的团队中工作,这将很有用。
演示版
将文件添加到项目
从项目中删除文件
单个文件删除
多文件删除
这个怎么运作
当您切换到文件系统树或不在文件系统树中最近的.csproj保存文件时,系统将提示您。
选择“关闭”将在状态栏中添加一个项目,并且在您打开文件时不再询问您。
文件不在csproj中
csproj中包含的文件
您可以通过命令面板将文件添加到csproj:
或通过文件资源管理器中的上下文菜单:
扩展设置
此扩展程序提供以下设置:
设定键
描述
csproj.enable
启用/禁用此扩展名。
csproj.itemType
从文件扩展名到csproj XML元素的映射。 默认为: { "*": "Content
VS.net VSS时,编译报错:未能向文件“.csproj.FileListAbsolute.txt”写入命令行 对路径 的访问被拒绝。
09-06
在VSS上把项目的Bin和Obj目录删除,然后重新取出项目,编译成功。
无法读取项目文件 .csproj,请确认 Import 声明中的路径正确
07-09
无法读取项目文件 .csproj,请确认 Import 声明中的路径正确.doc
csproj-check:检查.csproj文件,以确保它们不引用丢失的文件
05-03
csproj检查 检查Visual Studio csproj文件中的错误。 可用作git pre-commit钩子。安装npm i -g csproj-check 用法csproj-check # defaults to **/*csproj-check a/specific/project.csproj another/project.csproj...
Make2CSProjUpdater:从源文件列表更新.csproj ItemGroupCompile元素
05-20
作为项目的作者,有大量的Mono .csproj文件与Makefile源列表不。 Makefile源列表是已知的良好来源,因为它们用于构建Mono,而在该容量中不使用项目文件。 但是,在Mono编译器(mcs.exe)和PlayScript编译器(playc....
c# Thread、ThreadPool、Task有什么区别,什么时候用,以及Task的使用
m0_37805255的博客
09-04
3838
c# Thread、ThreadPool、Task有什么区别,什么时候用,以及Task的使用
这三者都是为了处理耗时任务,且都是异步的。
Thread
Thread就是Thread,需要自己调度,适合长跑型的操作。
ThreadPoll
ThreadPool是Thread基础上的一个线程池,目的是减少频繁创建线程的开销。线程很贵,要开新的stack,要增加CPU上下文切换,所以Threa...
NuGet 是什么? 理解与使用
m0_37805255的博客
08-29
3605
NuGet 是什么? 理解与使用
NuGet 是一个自由开源软件包管理系统,用于Microsoft开发平台,以前称NuPack。
NuGet 作为 Visual Studio 扩展,能够简化在 Visual Studio 项目中添加、更新和删除库(部署为程序包)的操作。NuGet 包是打包成单个ZIP文件,文件扩展名是 .nupkg,使用开放打包约定(OPC)格式,包好编译代码(Dll)、与...
事件监听机制——Java vs. C#
m0_37805255的博客
09-02
469
事件监听机制——Java vs. C#
C#语言类似Java,但两者之间的差别还是显而易见的,比如下面要说到的——事件监听机制。
Java的事件监听机制
Java中的事件监听是整个Java消息传递的基础和关键。其中涉及三类对象:事件源(Event Source)、事件(Event)、事件监听器(Event Listener)。
事件源:事件发生的场所,通常就是各个组件,比如一个按钮,或...
.csproj文件怎么打开
最新发布
11-15
你可以使用Visual Studio打开.csproj文件。如果你没有安装Visual Studio,你也可以使用文本编辑器打开.csproj文件,例如Notepad++或Visual Studio Code。在文本编辑器中打开.csproj文件,你可以查看和编辑项目文件的XML代码。请注意,如果你不熟悉XML语法和项目文件的结构,不建议直接编辑.csproj文件。
“相关推荐”对你有帮助么?
非常没帮助
没帮助
一般
有帮助
非常有帮助
提交
RayRings
CSDN认证博客专家
CSDN认证企业博客
码龄7年
暂无认证
55
原创
4万+
周排名
28万+
总排名
25万+
访问
等级
2346
积分
200
粉丝
258
获赞
77
评论
1117
收藏
私信
关注
热门文章
C语言零基础入门(一 简介)
33070
5G学习:5G总体架构
32014
Wasserstein距离
27135
.csproj 文件
15588
在Modbus主站与从站之间进行大数据量通信的方法
12897
分类专栏
Shell
编程
计算机硬核
2篇
5G
4篇
数据库
3篇
C++
1篇
硬件系统
1篇
Git
3篇
面试经验
2篇
.NET
3篇
企业架构
1篇
C#
6篇
C
8篇
论文笔记
1篇
Java
6篇
云计算
高数/线代/概率论
1篇
机器学习
5篇
深度学习
1篇
通信
16篇
最新评论
Wasserstein距离
Tisfy:
Wasserstein距离
以後╮的路、:
你也太夸张了吧
5G学习:5G基础概念
大风车一直转悠悠:
很有科普性的一篇文章
c# Thread、ThreadPool、Task有什么区别,什么时候用,以及Task的使用
HT002..:
threadpool不是能取消线程?、
为什么样本方差(sample variance)的分母是 n-1?
ghost_heartbeat:
专门登陆来喷你的,抄别人作业都抄不明白?
最新文章
MAC突然打不开Notion,你遇到过这个问题吗?
聊聊内存那点事儿
二进制、八进制、十进制以及十六进制之间的转换
2023年1篇
2022年2篇
2021年7篇
2020年4篇
2019年53篇
目录
目录
分类专栏
Shell
编程
计算机硬核
2篇
5G
4篇
数据库
3篇
C++
1篇
硬件系统
1篇
Git
3篇
面试经验
2篇
.NET
3篇
企业架构
1篇
C#
6篇
C
8篇
论文笔记
1篇
Java
6篇
云计算
高数/线代/概率论
1篇
机器学习
5篇
深度学习
1篇
通信
16篇
目录
评论 1
被折叠的 条评论
为什么被折叠?
到【灌水乐园】发言
查看更多评论
添加红包
祝福语
请填写红包祝福语或标题
红包数量
个
红包个数最小为10个
红包总金额
元
红包金额最低5元
余额支付
当前余额3.43元
前往充值 >
需支付:10.00元
取消
确定
下一步
知道了
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝
规则
hope_wisdom 发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额
0
抵扣说明:
1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。
余额充值
理解 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
如何运行 C# 程序 - Visual Studio (Windows) | Microsoft Learn
如何运行 C# 程序 - Visual Studio (Windows) | Microsoft Learn
跳转至主内容
此浏览器不再受支持。
请升级到 Microsoft Edge 以使用最新的功能、安全更新和技术支持。
下载 Microsoft Edge
有关 Internet Explorer 和 Microsoft Edge 的详细信息
目录
退出焦点模式
使用英语阅读
保存
目录
使用英语阅读
保存
打印
电子邮件
目录
在 Visual Studio 中运行 C# 程序
项目
03/16/2023
7 个参与者
反馈
本文内容
如何运行程序取决于你从什么开始执行、程序的类型,以及你是否想在调试器下运行。 最简单的是在 Visual Studio 中生成并运行一个打开的项目,在这种情况下,可执行以下操作:
按 F5,从 Visual Studio 菜单中选择“调试”>“开始执行(调试)”,或在 Visual Studio 工具栏上选择绿色的“开始”箭头和项目名称 。
你也可以按 Ctrl+F5,或从 Visual Studio 菜单中选择“调试”>“开始执行(不调试)”,直接运行而不调试 。
从项目开始
你可以运行 C# 项目或 .csproj 文件(如果是可运行的程序)。 如果项目包含带有 Main 方法的 C# 文件,并且其输出为可执行文件(.exe 文件),则很可能会在项目成功生成后运行该文件。 较新版本的 C# 不需要 Main 方法;相反,程序执行从顶级语句开始。 请参阅不含 Main 方法的程序。
如果你的程序代码已在 Visual Studio 项目中,请打开该项目。 你可以执行以下操作来打开项目:双击或点击 Windows 文件资源管理器中的 .csproj 文件;或者在 Visual Studio 中选择“打开项目”,浏览以找到 .csproj 文件,然后选择该文件。
在 Visual Studio 中加载项目后,如果 Visual Studio 解决方案包含多个项目,请确保将带有 Main 方法的项目设置为启动项目。 要设置启动项目,请右键单击“解决方案资源管理器”中的项目名称或节点,然后从上下文菜单中选择“设置为启动项目” 。
要运行程序,请按 Ctrl+F5,从顶部菜单中选择“调试”>“开始执行(不调试)”,或选择绿色的“开始”按钮 。
Visual Studio 会尝试生成并运行你的项目。 在 Visual Studio 屏幕的底部,生成输出显示在“输出”窗口中,生成错误显示在“错误列表”窗口中 。
如果生成成功,应用会以适合项目类型的方式运行。 控制台应用在终端窗口中运行,Windows 桌面应用在新的桌面窗口中启动,Web 应用在由 IIS Express 承载的浏览器中运行。
从代码开始
如果是从代码清单、代码文件或少量文件开始,请首先确保该代码来自受信任的源,并且是可运行的程序。 具有 Main 方法的任何应用都可能是可运行的程序,但对于当前版本的 C#,不含 Main 方法但具有顶级语句的程序也可以运行。 你可以使用“控制台应用程序”模板创建一个项目,以便在 Visual Studio 中使用该应用。
单个文件的代码列表
启动 Visual Studio,并打开一个空的 C# 控制台应用程序项目。
将项目 .cs 文件中的所有代码替换为代码清单或文件的内容。
将项目 .cs 文件重命名为与你的代码文件名一致。
磁盘上有多个代码清单或文件
启动 Visual Studio,并创建适当类型的新项目。 如果不确定,请使用 C#“控制台应用程序”。
在新项目中,将项目代码文件中的所有代码替换为第一个代码清单或文件的内容。
重命名项目代码文件,使其与你的代码文件名一致。
对于其余的每个代码文件:
右键单击“解决方案资源管理器”中的项目节点,然后选择“添加”>“现有项”,或选择该项目,然后按 Shift+Alt+A 。
浏览到并选择要导入到项目中的代码文件。
文件夹中有多个文件
如果文件夹中有多个文件,请先查找项目或解决方案文件。 Visual Studio 创建的程序具有项目和解决方案文件。 在 Windows 文件资源管理器中,查找扩展名为 .csproj 或 .sln 的文件 。 双击 .csproj 文件,在 Visual Studio 中打开它。 请参阅从 Visual Studio 解决方案或项目开始。
如果代码来自其他开发环境,则没有项目文件。 在 Visual Studio 中选择“打开”>“文件夹”,打开该文件夹 。 请参阅开发代码而无需创建项目或解决方案。
从 GitHub 或 Azure DevOps 存储库开始
如果要运行的代码位于 GitHub 或 Azure DevOps 存储库中,则可以使用 Visual Studio 直接从存储库打开项目。 请参阅打开存储库中的项目。
运行程序
要开始生成程序,请按 Visual Studio 工具栏上的绿色“开始”按钮,或者按 F5 或 Ctrl+F5 。 使用“开始”按钮或 F5 在调试器下运行程序 。
Visual Studio 会尝试在你的项目中生成并运行代码。 如果生成不成功,请参阅以下部分,了解有关如何成功生成项目的一些建议。
疑难解答
你的代码可能有错误。 或者代码可能是正确的,但它可能依赖于缺少的程序集或 NuGet 包,或者针对其他版本的 .NET。 在这些情况下,可以轻松地修复生成。
添加引用
要正确生成,代码必须正确,并具有对库或其他依赖项的正确引用。 代码中的红色波浪下划线或错误列表中的条目表明存在错误,即使在编译和运行程序之前也是如此。 如果错误与未解析的名称相关,则可能需要添加引用和/或 using 指令。 如果代码引用了任何缺失的程序集或 NuGet 包,则需要将这些引用添加到项目。
Visual Studio 会尝试帮助你识别缺少的引用。 如果名称未解析,编辑器中会出现灯泡图标。 选择灯泡,可以看到有关如何修复此问题的一些建议。 解决方法可能是:
添加 using 指令。
添加对程序集的引用。
安装 NuGet 包。
添加 using 指令
下面是缺少的 using 指令的示例。 你可以将 using System; 添加到代码文件的开头,以解析无法解析的名称 Console:
较新版本的 C# 支持对一些常用命名空间使用隐式 using 指令,因此,如果在创建项目时选择了该选项,则不需要它们。
添加程序集引用
.NET 引用可以是程序集或 NuGet 包。 在源代码中,发布者或作者通常会说明代码所需的程序集以及它所依赖的包。 要手动添加对项目的引用,请右键单击“解决方案资源管理器”中的“引用”节点,然后选择“添加引用” 。 在“引用管理器”中,找到并添加所需的程序集。
你可以按照使用引用管理器添加或删除引用中的说明查找程序集并添加引用。
添加 NuGet 包
如果 Visual Studio 检测到缺少 NuGet 包,则会显示一个灯泡,并提供安装包的选项:
如果这不能解决问题,或者 Visual Studio 找不到包,请尝试联机搜索包。 请参阅在 Visual Studio 中安装和使用 NuGet 包。
使用正确版本的 .NET
由于不同版本的 .NET Framework 具有一定的后向兼容性,因此较新的框架可能会运行针对较旧的框架编写的代码,且不需要进行任何更改。 但有时需要针对特定的 .NET Framework 版本。 你可能需要安装特定版本的 .NET Framework 或 .NET Core。 请参阅修改 Visual Studio。
要更改目标 .NET Framework 版本,请参阅更改目标框架。 有关详细信息,请参阅 .NET Framework 目标错误疑难解答。
后续步骤
阅读欢迎使用 Visual Studio IDE,探索 Visual Studio 开发环境。
创建自己的第一个 C# 应用
其他资源
加州消费者隐私法案 (CCPA) 禁用图标
你的隐私选择
主题
亮
暗
高对比度
早期版本
博客
参与
隐私
使用条款
商标
© Microsoft 2024
其他资源
本文内容
加州消费者隐私法案 (CCPA) 禁用图标
你的隐私选择
主题
亮
暗
高对比度
早期版本
博客
参与
隐私
使用条款
商标
© Microsoft 2024
理解 C# 项目 csproj 文件格式的本质和编译流程_.csproj-CSDN博客
>理解 C# 项目 csproj 文件格式的本质和编译流程_.csproj-CSDN博客
理解 C# 项目 csproj 文件格式的本质和编译流程
最新推荐文章于 2024-03-07 14:53:15 发布
我心依旧
最新推荐文章于 2024-03-07 14:53:15 发布
阅读量927
收藏
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 592 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 120 给你两个字符串 word1 和 word2。请你从 word1 开始,通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长,就将多出来的字母追加到合并后字符串的末尾。使用两个指针i和j,初始时分别指向两个字符串的首个位置。如果i没有超出word1的范围,就将word1[i]加入答案,并且将i移动一个位置;如果j没有超出word2的范围,就将word2[j]加入答案,并且将j移动一个位置。当i和j都超出对应的范围后,结束循环并返回答案即可。返回 合并后的字符串。 C#通过配置文件动态修改web.config内容 lxyforever5的博客 03-07 287 Web.setting.config内容,存放一些配置信息,内容具体情况具体设置。Web.aaa.config内容,存放连接数据库的信息。1. Web.config配置文件内的处理。3.进行动态修改,具体情况具体操作。 [C#]winform部署yolov9的onnx模型 FL1623863129的博客 03-04 922 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 896 可以尝试使用数据库管理工具(比如Access自带的修复工具)对数据库文件进行修复,或者尝试连接其他已知可用的数据库文件进行测试。5. 使用正确的连接字符串:在连接数据库时,需要使用正确的连接字符串来指定数据库文件的位置、类型和其他必要信息。总之,当遇到C#中不可识别的数据库格式错误时,重要的是要仔细检查并排除各种可能导致问题的原因,并采取适当的措施来解决问题,以确保应用程序能够顺利地连接和操作数据库。总之,当遇到数据库格式不可识别的错误时,首先需要仔细检查错误消息,确定出现错误的具体位置和原因。 ManualResetEvent 在线程中的使用C# 最新发布 weixin_40314351的博客 03-07 267 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万+ 总排名 4818 访问 等级 74 积分 1 粉丝 2 获赞 1 评论 5 收藏 私信 关注 热门文章 xLang 的类型转换 2169 理解 C# 项目 csproj 文件格式的本质和编译流程 927 用xLang写Timer事件 725 用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、付费专栏及课程。 余额充值 .NET 项目 SDK 概述 | Microsoft Learn 跳转至主内容 此浏览器不再受支持。 请升级到 Microsoft Edge 以使用最新的功能、安全更新和技术支持。
下载 Microsoft Edge
有关 Internet Explorer 和 Microsoft Edge 的详细信息
目录 退出焦点模式 使用英语阅读 保存 目录 使用英语阅读 保存 打印 Twitter LinkedIn Facebook 电子邮件 目录 .NET 项目 SDK
项目 04/11/2023
7 个参与者
反馈 本文内容 .NET Core 和 .NET 5 及更高版本项目与软件开发工具包 (SDK) 关联。 每个项目 SDK 都是一组 MSBuild 目标和相关的任务,它们负责编译、打包和发布代码。 引用项目 SDK 的项目有时称为“SDK 样式的项目”。 可用的 SDK 有以下 SDK 可用: ID 描述 存储库 Microsoft.NET.Sdk .NET SDK https://github.com/dotnet/sdk Microsoft.NET.Sdk.Web .NET Web SDK https://github.com/dotnet/sdk Microsoft.NET.Sdk.BlazorWebAssembly The .NET Blazor WebAssembly SDK https://github.com/dotnet/aspnetcore Microsoft.NET.Sdk.Razor .NET Razor SDK https://github.com/dotnet/aspnetcore Microsoft.NET.Sdk.Worker .NET 辅助角色服务 SDK Microsoft.NET.Sdk.WindowsDesktop .NET 桌面 SDK,其中包括 Windows 窗体 (WinForms) 和 Windows Presentation Foundation (WPF)。* https://github.com/dotnet/winforms 和 https://github.com/dotnet/wpf .NET SDK 是 .NET 的基本 SDK。 其他 SDK 引用 .NET SDK,与其他 SDK 关联的项目具有所有可用的 .NET SDK 属性。 例如,Web SDK 依赖于 .NET SDK 和 Razor SDK。 你还可以创建自己的 SDK,并通过 NuGet 进行分发。 * 从 .NET 5 开始,Windows 窗体和 Windows Presentation Foundation (WPF) 项目应指定 .NET SDK (Microsoft.NET.Sdk),而不是 Microsoft.NET.Sdk.WindowsDesktop。 对于这些项目,将 TargetFramework 设置为 net5.0-windows 并将 UseWPF 或 UseWindowsForms 设置为 true 的操作会自动导入 Windows 桌面 SDK。 如果你的项目面向 .NET 5 或更高版本,并指定 Microsoft.NET.Sdk.WindowsDesktop SDK,则会收到生成警告 NETSDK1137。 项目文件 .NET 项目基于 MSBuild 格式。 具有扩展名(如用于 C# 项目的 .csproj 和用于 F# 项目的 .fsproj)的项目文件都是 XML 格式的 。 MSBuild 项目文件的根元素是 Project 元素。 Project 元素有一个可选的 Sdk 属性,该属性指定要使用的 SDK(和版本)。 若要使用 .NET 工具并构建你的代码,请将 Sdk 属性设置为可用 SDK 表中的其中一个 ID。 ... 若要指定来自 NuGet 的 SDK,请在名称末尾包含版本,或者在 global.json 文件中指定名称和版本。 ... 另一种指定 SDK 的方法是使用顶层 Sdk 元素: ... 以这些方式之一引用 SDK 可以极大地简化 .NET 的项目文件。 在评估项目时,MSBuild 在项目文件的顶部和底部分别为 Sdk.props 和 Sdk.targets 添加隐式导入。 ... 提示 在 Windows 计算机上,Sdk.props 和 Sdk.targets 文件位于 %ProgramFiles%\dotnet\sdk\[version]\Sdks\Microsoft.NET.Sdk\Sdk 文件夹中。 预处理项目文件 使用 dotnet msbuild -preprocess 命令,可以看到 MSBuild 在包含 SDK 及其目标之后所显示的完全扩展的项目。 dotnet msbuild 命令的预处理开关显示导入的文件、文件源及其在生成中的参与情况,而无需实际生成项目。 如果项目有多个目标框架,请将命令的结果指定为 MSBuild 属性,使其仅侧重于框架之一。 例如: dotnet msbuild -property:TargetFramework=netcoreapp2.0 -preprocess:output.xml 默认包含和排除的内容 SDK 中定义了 Compile 项、嵌入的资源和 None 项默认包含和排除的内容。 与非 SDK .NET 框架项目不同,你无需在项目文件中指定这些项,因为默认设置涵盖了最常见的用例。 此行为使得项目文件更小、更易于理解和手动编辑(如需要)。 下表显示在 .NET SDK 中包含和排除的元素和 glob: 元素 包含 glob 排除 glob 删除 glob Compile **/*.cs(或其他语言扩展名) **/*.user; **/*.*proj; **/*.sln; **/*.vssscc 空值 EmbeddedResource **/*.resx **/*.user; **/*.*proj; **/*.sln; **/*.vssscc 空值 None **/* **/*.user; **/*.*proj; **/*.sln; **/*.vssscc **/*.cs; **/*.resx 注意 默认情况下,由 $(BaseOutputPath) 和 $(BaseIntermediateOutputPath) MSBuild 属性表示的 ./bin 和 ./obj 文件夹不包含在 glob 中。 排除由 DefaultItemExcludes 属性表示。 .NET 桌面 SDK 对于 WPF 有更多包含和排除的内容。 有关详细信息,请参阅 WPF 默认包含和排除的内容。 生成错误 如果在项目文件中显式定义这些项中的任何项,可能会出现类似于以下内容的“NETSDK1022”生成错误: 包含重复的“Compile”项。 默认情况下,.NET SDK 包括项目目录中的“Compile”项。 可从项目文件中删除这些项,或如果想要在项目文件中显式包括它们,则将“EnableDefaultCompileItems”属性设为“false”。 包含重复的“EmbeddedResource”项。 默认情况下,.NET SDK 包括项目目录中的“EmbeddedResource”项。 可从项目文件中删除这些项,或如果想要在项目文件中显式包括它们,则将“EnableDefaultEmbeddedResourceItems”属性设为“false”。 若要解决此错误,请执行以下操作之一: 删除与上表中列出的隐式项匹配的显式 Compile、EmbeddedResource 或 None 项。 若要禁用所有隐式文件包含,请将 EnableDefaultItems 属性设置为 false: 若要指定某些文件通过应用发布,仍可以使用相应的已知 MSBuild 机制来实现(例如 Content 元素)。 可选择仅禁用 Compile、EmbeddedResource 或 None glob,方法是将 EnableDefaultCompileItems、EnableDefaultEmbeddedResourceItems 或 EnableDefaultNoneItems 属性设置为 false: 如果仅禁用 Compile glob,则 Visual Studio 中的解决方案资源管理器仍将 *.cs 项显示为项目的一部分,并作为 None 项包含在内。 若要禁用隐式 None glob,请将 EnableDefaultNoneItems 也设置为 false。 隐式 using 指令 从 .NET 6 开始,隐式 global using 指令将添加到新的 C# 项目中。 这意味着可以使用这些命名空间中定义的类型,而无需指定完全限定的名称或手动添加 using 指令。 隐式方面是指向项目的 obj 目录中生成的文件添加 global using 指令这一事实。 为使用以下 SDK 之一的项目添加隐式 global using 指令: Microsoft.NET.Sdk Microsoft.NET.Sdk.Web Microsoft.NET.Sdk.Worker Microsoft.NET.Sdk.WindowsDesktop 为基于项目 SDK 的一组默认命名空间中的每个命名空间添加 global using 指令。 下表显示了这些默认命名空间。 SDK 中 IsInRole 中的声明 默认命名空间 Microsoft.NET.Sdk SystemSystem.Collections.GenericSystem.IOSystem.LinqSystem.Net.HttpSystem.ThreadingSystem.Threading.Tasks Microsoft.NET.Sdk.Web System.Net.Http.JsonMicrosoft.AspNetCore.BuilderMicrosoft.AspNetCore.HostingMicrosoft.AspNetCore.HttpMicrosoft.AspNetCore.RoutingMicrosoft.Extensions.ConfigurationMicrosoft.Extensions.DependencyInjectionMicrosoft.Extensions.HostingMicrosoft.Extensions.Logging Microsoft.NET.Sdk.Worker Microsoft.Extensions.ConfigurationMicrosoft.Extensions.DependencyInjectionMicrosoft.Extensions.HostingMicrosoft.Extensions.Logging Microsoft.NET.Sdk.WindowsDesktop(Windows 窗体) Microsoft.NET.Sdk 命名空间System.DrawingSystem.Windows.Forms Microsoft.NET.Sdk.WindowsDesktop (WPF) Microsoft.NET.Sdk 命名空间已删除 System.IO已删除 System.Net.Http 若要禁用此功能,或要在现有的 C# 项目中启用隐式 global using 指令,可通过 ImplicitUsingsMSBuild 属性实现。 可以通过向项目文件添加 Using 项(或针对 Visual Basic 项目添加 Import 项)来指定其他隐式 global using 指令,例如: 隐式包引用 如果以 .NET Core 1.0 - 2.2 或 .NET Standard 1.0 - 2.0 为目标,则 .NET SDK 会添加对某些元包的隐式引用。 元包是一种基于框架的包,其中只包含对其他包的依赖项。 元包根据项目文件的 TargetFramework 或 TargetFrameworks 属性中指定的目标框架被隐式引用。 如果需要,可以使用 DisableImplicitFrameworkReferences 属性来禁用隐式包引用,并只添加对所需的框架或包的显式引用。 建议: 如果以 .NET Framework、.NET Core 1.0 - 2.2 或 .NET Standard 1.0 - 2.0 为目标,不要通过项目文件中的 如果在以 .NET Core 1.0 - 2.2 为目标时需要特定版本的运行时,请在项目中使用 如果在以 .NET Standard 1.0 - 2.0 为目标时需要特定版本的 NETStandard.Library 元包,则可以使用 生成事件 在 SDK 样式的项目中,请使用名为 PreBuild 或 PostBuild 的 MSBuild 目标,并设置 PreBuild 的 BeforeTargets 属性或 PostBuild 的 AfterTargets 属性。 注意 可以为 MSBuild 目标使用任何名称。 但是,Visual Studio IDE 会识别 PreBuild 和 PostBuild 目标,因此通过使用这些名称,可以在 IDE 中编辑命令。 不建议在 SDK 样式的项目中使用属性 PreBuildEvent 和 PostBuildEvent,因为无法解析 $(ProjectDir) 这样的宏。 例如,以下代码是不受支持的: 自定义生成 可以通过多种方式自定义生成。 建议通过将属性作为参数传递给 msbuild 或 dotnet 命令来重写该属性。 还可以将属性添加到项目文件或 Directory.Build.props 文件中。 有关 .NET 项目的有用属性列表,请参见 .NET SDK 项目的 MSBuild 参考。 提示 从命令行创建新的 Directory.Build.props 文件的一种简单方法是使用存储库根目录中的命令 dotnet new buildprops。 自定义目标 .NET 项目可以打包自定义的 MSBuild 目标和属性,以供使用该包的项目使用。 如果要执行以下操作,请使用此类型的可扩展性: 扩展生成过程。 访问生成过程的工件,如生成的文件。 检查调用生成的配置。 通过在项目的生成文件夹中以 以下 XML 是 .csproj 文件中的一个片段,该文件指示 dotnet pack 命令打包的内容。 ... ... 若要在项目中使用自定义目标,请添加指向包及其版本的 PackageReference 元素。 与工具不同,自定义目标包包含在消费项目的依赖项闭包中。 你可以配置自定义目标的使用方式。 由于它是 MSBuild 目标,因此会依赖于给定的目标并在另一个目标后运行,也可使用 dotnet msbuild -t: 请参阅 自定义您的生成过程 (MSBuild) 如何使用 MSBuild 项目 SDK 使用 NuGet 打包自定义 MSBuild 目标和属性 在 GitHub 上与我们协作
可以在 GitHub 上找到此内容的源,还可以在其中创建和查看问题和拉取请求。 有关详细信息,请参阅参与者指南。
.NET 提出文档问题 提供产品反馈 反馈 Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see: https://aka.ms/ContentUserFeedback. 提交和查看相关反馈 此产品 此页面 查看所有页面反馈 其他资源 加州消费者隐私法案 (CCPA) 禁用图标 你的隐私选择 主题
亮
暗
高对比度 早期版本 博客 参与 隐私 使用条款 商标 © Microsoft 2024 其他资源 本文内容 加州消费者隐私法案 (CCPA) 禁用图标 你的隐私选择 主题
亮
暗
高对比度 早期版本 博客 参与 隐私 使用条款 商标 © Microsoft 2024 常用的 MSBuild 项目属性 - MSBuild | Microsoft Learn 跳转至主内容 此浏览器不再受支持。 请升级到 Microsoft Edge 以使用最新的功能、安全更新和技术支持。
下载 Microsoft Edge
有关 Internet Explorer 和 Microsoft Edge 的详细信息
目录 退出焦点模式 语言 使用英语阅读 保存 目录 使用英语阅读 保存 打印 Twitter LinkedIn Facebook 电子邮件 目录 常用的 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 理解 C# 项目 csproj 文件格式的本质和编译流程_csproj build 单独编译一个工程-CSDN博客 理解 C# 项目 csproj 文件格式的本质和编译流程 最新推荐文章于 2023-07-21 21:10:44 发布 sinolover 最新推荐文章于 2023-07-21 21:10:44 发布 阅读量521 收藏 5 点赞数 2 分类专栏: # Visualstudio 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/sinolover/article/details/104496773 版权 Visualstudio 专栏收录该内容 29 篇文章 1 订阅 订阅专栏 写了这么多个 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 中插入了以上代码。 原文地址:https://walterlv.github.io/post/understand-the-csproj.html 作者:欲与星辰眠 链接:https://www.jianshu.com/p/0ff2a76167fc 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 优惠劵 sinolover 关注 关注 2 点赞 踩 5 收藏 觉得还不错? 一键收藏 知道了 0 评论 理解 C# 项目 csproj 文件格式的本质和编译流程 写了这么多个 C# 项目,是否对项目文件 csproj 有一些了解呢?Visual Studio 是怎么让 csproj 中的内容正确显示出来的呢?更深入的,我能够自己扩展 csproj 的功能吗?本文将直接从 csproj 文件格式的本质来看以上这些问题。阅读本文,你将:可以通读 csproj 文件,并说出其中每一行的含义可以手工修改 csproj 文件,以实现你希望达到的高级功... 复制链接 扫一扫 专栏目录 获取C#项目包含的所有程序文件的源代码 12-12 获取C#项目包含的所有程序文件的源代码,包含项目文件SLN的解析,解决方案CSPROJ的解析,XML命名空间的适配。 C# 项目,当提示缺少.csproj 文件,如何处理? YouChuanChiMeng的博客 12-01 1631 C# 项目,当提示缺少.csproj 文件,如何处理? 参与评论 您还未登录,请先 登录 后发表或查看评论 csproj文件常用设置及C#注释常用写法 博客 06-29 774 csproj文件常用设置及C#注释常用写法 ASP.NET 代码找不到 .csproj 文件 ? 因为这是.Net 2.0项目 brook0344的专栏 04-19 2274 c# 在现有项目中添加另一项目中的整个文件夹(多层)的方法(.csproj文件) lanshahewu的博客 03-16 2706 如题,如下图 右键–《解决方案“lesson5”(1个项目)》–“添加”–“现有项目”,找到项目A的.csproj文件 下一步: 下一步,目标文件夹已添加,如下: 添加项目引用,如下: 最后一步,如下: 确定,万事大吉 ... 【CSharp】关于xxx.csproj文件的理解 jn10010537的博客 07-21 592 Visual Studio会根据csproj里的内容来定义来管理项目文件以及相关其他一些种类非常丰富的数据及操作。.csproj文件记录了与工程有关的相关信息,例如包含的文件,程序的版本,所生成的文件的类型和位置信息等。在.NET框架的开发环境中建立项目时,会产生.csproj文件,这是C#的项目工程文件。csproj的全称是C Sharp Project的缩写,是C#项目文件的扩展名。上面的iRayBase.csproj 文件后缀是 .csproj。在示例代码里,遇到.csproj 文件。 .csproj 文件 热门推荐 m0_37805255的博客 08-28 1万+ .csproj 文件 .csproj,是C#项目文件的扩展名,它是“C Sharp Project”的缩写。.net开发环境中建立项目时,会产生.csproj文件,这是C#的工程文件,其中记录了与工程有关的相关信息,例如包含的文件,程序的版本,所生成的文件的类型和位置信息等。 【作用】 .csproj究竟是做什么用的?它是给开发工具用的,例如我们再熟悉不过的Visual Studio,以... Visual Studio 的csproj项目文件简释 只会C#的程序猿 07-08 1594 Visual Studio 的csproj项目文件简释文档结构分布式csproj项目文件props文件引用props文件 文档结构 vs2015修改csproj文件实现vs2019中自动添加文件功能 三体问题 09-07 2427 一、问题 在vs2019中,把cs后缀名的文件放入工程下文件夹中,就会自动导入工程。 vs2019的csproj工程配置文件如下: 可以看到并没有class1.cs,ss.cs,Test.cs的相关配置,确引用了相关文件夹,可以判定,是编译器自动帮忙识别了其中的文件 vs2019的csproj工程配置文件如下: 引用cs文件时,需要在 ... 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%。 【转】VS中常用图标提示含义 sinolover的专栏 04-28 2611 转自:https://www.cnblogs.com/zhjason/articles/14044190.html “类视图”和“对象浏览器”图标 “类视图”和“对象浏览器”显示表示代码实体的图标,如命名空间、类、函数和变量 。下表展示和描述了图标。 图标 描述 图标 描述 命名空间 方法或函数 类 运算符 接口 Property 结构 字段或变量 联合 . VS的包含目录、库目录、引用目录、可执行目录解释 sinolover的专栏 02-27 2427 来源:包含目录、库目录、附加包含目录、附加库目录、附加依赖项之详解 学习备份 VS项目中的包含目录、库目录、附加包含目录、附加库目录、附加依赖项均在”项目->属性->配置属性”下进行配置,具体说明如下: VC++目录: 包含目录:寻找#include 库目录:寻找.lib文件的搜索目录 C/C++: ... 【转】visual studio 2019 (vs) 显示右侧缩略图_缩略图_滚动条 sinolover的专栏 09-17 2201 1. 工具 ->选项 2.文件编辑器 ->选项对应的语言(Basic, C#, C/C++....) ->行为 ->使用垂直滚动条的缩略图模式(M) 效果: Microsoft.CSharp.dll程序集的作用 sinolover的专栏 02-27 1960 《C#与.NET 4高级程序设计:第5版》第18章动态类型和动态语言运行时,本章,我们将学习dynamic关键字的方方面面,理解如何使用DLR (Dynamic Language Runtime,动态语言运行时)将松散的类型映射到正确的内存对象。理解了DLR提供的诸多服务之后,你将看到一些示例,它们使用动态类型来简化后期绑定方法的调用(通过反射服务)并且可以方便地与遗留的COM库进行通信。本节为大... c#如何生成csproj文件 最新发布 07-28 5. csproj 文件是一个 XML 格式的文件,其中包含了项目的配置信息。你可以根据需要添加、修改或删除一些元素。 6. 例如,你可以添加 ` “相关推荐”对你有帮助么? 非常没帮助 没帮助 一般 有帮助 非常有帮助 提交 sinolover CSDN认证博客专家 CSDN认证企业博客 码龄15年 暂无认证 1636 原创 1万+ 周排名 3071 总排名 268万+ 访问 等级 2万+ 积分 813 粉丝 1129 获赞 336 评论 6268 收藏 私信 关注 热门文章 Ubuntu下安装Chrome浏览器的两个方法 218023 什么是欧拉角/姿态角? 95932 Windows电脑SMB共享设置方法 80057 【转】你不能访问此共享文件夹,因为你组织的安全策略阻止未经身份验证的来宾访问 61996 最新的windows xp sp3序列号 xp序列号 37159 分类专栏 vba4 4篇 DCMTK 8篇 vba81 乔克灬叔叔 1篇 菜鸟入门篇-PACS客户端 4篇 QT 16篇 CPP 31篇 CT 14篇 CE 1篇 CT窗_层_面_概念 5篇 未分类 80篇 CAN 2篇 Win32 21篇 VTK 6篇 vtk用户指南 VTK修炼之道 2篇 DICOM 32篇 zssure 8篇 fo-DICOM 3篇 Dicom 学习笔记 7篇 DICOM入门 3篇 DICOM网络协议 5篇 csharp 66篇 CLR 18篇 国密加密 8篇 常见类继承关系 1篇 C# stream 5篇 带你玩转Visual Studio 4篇 C#的三种异步的详细介绍及实现 4篇 NameSpace 及命名规范 8篇 文件操作 6篇 异步编程系列 27篇 分层架构实战 2篇 c#变迁史 11篇 Log4Net 1篇 Visualstudio 29篇 集合接口 7篇 同步与异步系列之二 8篇 c#进阶 15篇 各类锁 5篇 ASP.NET MVC 入门 15篇 ASP.NET Core管道深度剖析 6篇 IIS管道 17篇 单元测试 5篇 多线程系列 49篇 C#多线程之旅 12篇 WebForm 14篇 WebApi系列 25篇 WebService 4篇 WebSocket 12篇 阿里技术专家详解 DDD 系列 2篇 逆变与协变 4篇 DotNet进阶 22篇 你必须知道的.NET 37篇 Quartz.Net详解 14篇 net框架 13篇 abp 17篇 ABP分析 48篇 ABP入门系列 20篇 不知道 11篇 Entity FrameWork详解 28篇 NuGet 12篇 同步异步系列 22篇 WCF 3篇 WPF 21篇 C#Socket编程详解 1篇 CLRProfile 2篇 通用知识 2篇 刨根究底字符编码 21篇 刨根究底正则表达式 2篇 Postman系列 6篇 TCP_IP 7篇 svn 6篇 人工智能 5篇 Office 365开发入门指南 2篇 Microsoft Teams快速上手系列 5篇 OData 6篇 Git 10篇 Dynamics365 8篇 XRM 7篇 D365 FO第三方集成 6篇 Dynamics 365 目录 5篇 Dynamics CRM 365零基础入门学习 9篇 蜗牛星际 4篇 RPA 1篇 笔记 2篇 数据库 4篇 Access SQLServer 16篇 MySql 10篇 Oracle 分布式事务 17篇 Quenue 1篇 RabbitMQ六种队列模式 5篇 MemCached Redis 4篇 MonogoDB 2篇 HBASE Neo4j 软件工程 10篇 CI_CD 2篇 状态机 7篇 Axure RP 11篇 消息队列 2篇 AOP 3篇 设计原则 2篇 设计模式 6篇 CSharp23设计模式 26篇 白话设计模式 28 讲 2篇 Scrum 3篇 软件模式 1篇 UML 13篇 系统架构 1篇 三高 1篇 认证考试 1篇 Ali云 1篇 Cloudera 1篇 微软认证 4篇 前端 14篇 Magento 8篇 VUE 2篇 刨根究底CSS 2篇 EasyUI学习总结(一) 1篇 14-JS系列 6篇 13-CSS系列 14篇 knockoutjs 8篇 razor 1篇 sharepoint 133篇 SP学习笔记—架构系列 13篇 SP学习笔记—ECM系列 4篇 SP学习笔记—Ribbon系列 1篇 SP学习笔记—Site Definition系列 4篇 SP无代码开发实例 3篇 SP学习札记 6篇 SharePoint服务器端对象模型 15篇 tfs 41篇 MTM 4篇 network 10篇 天猫精灵 2篇 一步步编写操作系统 83篇 linux 48篇 azure 29篇 MicrosoftGraphic 16篇 Azure手把手系列 6篇 onedriver 8篇 云安全 17篇 Azure Sentinel 18篇 python 2篇 vc 15篇 Windows 6篇 Office 1篇 PowerBI 8篇 Ros 34篇 由浅到深理解ROS 10篇 TurtleBot3 4篇 vba1 6篇 masm 84篇 Java 61篇 Java Web 5篇 最新评论 【转】.Net中的异步编程总结 qq_41990167: a er 【转】VNC不同软件之间的联系与区别 Alwaysbeyoung: 物联网应用好多还是用vnc,能不能用rdp代替呢毕竟现在终端性能都不错了 天猫精灵方糖拆解报告和芯片详解 2301_80964193: 问下博主这个SQ71B在淘宝怎么搜? 【转】在无人值守程序(服务)中调用Microsoft Graph 记得.zZ: 大哥问下,https://login.windows.net/59723f6b-2d14-49fe-827a-8d04f9fe7a68/oauth2/token中间的这个ID是什么?租户ID?还是调接口生成的? ABP入门系列(6)——定义导航菜单 TMC3.0: 为什么我的导航会在左边 您愿意向朋友推荐“博客详情页”吗? 强烈不推荐 不推荐 一般般 推荐 强烈推荐 提交 最新文章 Visual Studio Code c++函数跳转时显示“未找到函数定义” vscode no definition for 鼠标提示也没有 excel 人民币中文大写转换无宏完美版 脚本:自动修改wsl中主机Host的IP 2023年5篇 2022年50篇 2021年394篇 2020年905篇 2019年450篇 2018年2篇 2017年21篇 2014年3篇 目录 目录 分类专栏 vba4 4篇 DCMTK 8篇 vba81 乔克灬叔叔 1篇 菜鸟入门篇-PACS客户端 4篇 QT 16篇 CPP 31篇 CT 14篇 CE 1篇 CT窗_层_面_概念 5篇 未分类 80篇 CAN 2篇 Win32 21篇 VTK 6篇 vtk用户指南 VTK修炼之道 2篇 DICOM 32篇 zssure 8篇 fo-DICOM 3篇 Dicom 学习笔记 7篇 DICOM入门 3篇 DICOM网络协议 5篇 csharp 66篇 CLR 18篇 国密加密 8篇 常见类继承关系 1篇 C# stream 5篇 带你玩转Visual Studio 4篇 C#的三种异步的详细介绍及实现 4篇 NameSpace 及命名规范 8篇 文件操作 6篇 异步编程系列 27篇 分层架构实战 2篇 c#变迁史 11篇 Log4Net 1篇 Visualstudio 29篇 集合接口 7篇 同步与异步系列之二 8篇 c#进阶 15篇 各类锁 5篇 ASP.NET MVC 入门 15篇 ASP.NET Core管道深度剖析 6篇 IIS管道 17篇 单元测试 5篇 多线程系列 49篇 C#多线程之旅 12篇 WebForm 14篇 WebApi系列 25篇 WebService 4篇 WebSocket 12篇 阿里技术专家详解 DDD 系列 2篇 逆变与协变 4篇 DotNet进阶 22篇 你必须知道的.NET 37篇 Quartz.Net详解 14篇 net框架 13篇 abp 17篇 ABP分析 48篇 ABP入门系列 20篇 不知道 11篇 Entity FrameWork详解 28篇 NuGet 12篇 同步异步系列 22篇 WCF 3篇 WPF 21篇 C#Socket编程详解 1篇 CLRProfile 2篇 通用知识 2篇 刨根究底字符编码 21篇 刨根究底正则表达式 2篇 Postman系列 6篇 TCP_IP 7篇 svn 6篇 人工智能 5篇 Office 365开发入门指南 2篇 Microsoft Teams快速上手系列 5篇 OData 6篇 Git 10篇 Dynamics365 8篇 XRM 7篇 D365 FO第三方集成 6篇 Dynamics 365 目录 5篇 Dynamics CRM 365零基础入门学习 9篇 蜗牛星际 4篇 RPA 1篇 笔记 2篇 数据库 4篇 Access SQLServer 16篇 MySql 10篇 Oracle 分布式事务 17篇 Quenue 1篇 RabbitMQ六种队列模式 5篇 MemCached Redis 4篇 MonogoDB 2篇 HBASE Neo4j 软件工程 10篇 CI_CD 2篇 状态机 7篇 Axure RP 11篇 消息队列 2篇 AOP 3篇 设计原则 2篇 设计模式 6篇 CSharp23设计模式 26篇 白话设计模式 28 讲 2篇 Scrum 3篇 软件模式 1篇 UML 13篇 系统架构 1篇 三高 1篇 认证考试 1篇 Ali云 1篇 Cloudera 1篇 微软认证 4篇 前端 14篇 Magento 8篇 VUE 2篇 刨根究底CSS 2篇 EasyUI学习总结(一) 1篇 14-JS系列 6篇 13-CSS系列 14篇 knockoutjs 8篇 razor 1篇 sharepoint 133篇 SP学习笔记—架构系列 13篇 SP学习笔记—ECM系列 4篇 SP学习笔记—Ribbon系列 1篇 SP学习笔记—Site Definition系列 4篇 SP无代码开发实例 3篇 SP学习札记 6篇 SharePoint服务器端对象模型 15篇 tfs 41篇 MTM 4篇 network 10篇 天猫精灵 2篇 一步步编写操作系统 83篇 linux 48篇 azure 29篇 MicrosoftGraphic 16篇 Azure手把手系列 6篇 onedriver 8篇 云安全 17篇 Azure Sentinel 18篇 python 2篇 vc 15篇 Windows 6篇 Office 1篇 PowerBI 8篇 Ros 34篇 由浅到深理解ROS 10篇 TurtleBot3 4篇 vba1 6篇 masm 84篇 Java 61篇 Java Web 5篇 目录 评论 被折叠的 条评论 为什么被折叠? 到【灌水乐园】发言 查看更多评论 添加红包 祝福语 请填写红包祝福语或标题 红包数量 个 红包个数最小为10个 红包总金额 元 红包金额最低5元 余额支付 当前余额3.43元 前往充值 > 需支付:10.00元 取消 确定 下一步 知道了 成就一亿技术人! 领取后你会自动成为博主和红包主的粉丝 规则 hope_wisdom 发出的红包 实付元 使用余额支付 点击重新获取 扫码支付 钱包余额 0 抵扣说明: 1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。 余额充值 .Csproj文件学习笔记 - N-COUNT - 博客园 会员 周边 新闻 博问 AI培训 云市场 所有博客 当前博客 我的博客 我的园子 账号设置 简洁模式 ... 退出登录 注册 登录 N-COUNT 学习进步 博客园 首页 新随笔 联系 订阅 管理 .Csproj文件学习笔记 .csproj是基于XML的格式。以下示例显示了使用.NET Core项目的根节点Microsoft.NET.Sdk。对于Web项目,使用的SDK是Microsoft.NET.Sdk.Web。 我们可以自己直接编辑.csproj文件,并手动添加必要的项目。所需的确切代码取决于需要链接的文件类型以及所需的MSBuild操作类型。 Visual Studio现在使用.csproj文件来管理项目。我们可以通过右键单击项目并选择Edit 上面项目的.csproj如下所示。 csproj文件包括与目标.NET Framework,项目文件夹,NuGet程序包引用等相关的设置。 .csproj是基于XML的格式。以下示例显示了使用.NET Core项目的根节点Microsoft.NET.Sdk。对于Web项目,使用的SDK是Microsoft.NET.Sdk.Web。 ... 我们可以自己直接编辑.csproj文件,并手动添加必要的项目。所需的确切代码取决于需要链接的文件类型以及所需的MSBuild操作类型。 例如,如果我们要通过链接从项目外部添加.cs文件,则可以使用嵌套在 Include给出项目文件夹中文件的相对路径,Link属性告诉MSBuild将文件添加为链接,以及应该用于该文件的名称。甚至还可以更改文件名。 对于诸如JSON配置文件之类的内容文件,我们可以使用 在此示例中,我们将CopyToOutputDirectory设置为PreserveNewest,以便在构建或发布项目时将文件复制到输出目录。 PackageReference元素指定项目的NuGet依赖。Include属性指定包ID Version属性指定要还原的软件包的版本。 IncludeAssets属性指定 ExcludeAssets属性指定 PrivateAssets属性指定 多个目标框架 我们可以创建.NET Core应用程序并为其配置多个目标框架,以便它可以与所有已配置的目标框架一起运行。要定位多个框架,需要更改 条件引用 我们可能会遇到的一个问题是,需要根据要构建的目标引用不同的程序集或NuGet程序包。 例如,我们将以下方法添加到我们的库中,它将成功编译.NET Standard 2.0目标,但是.NET 4.6.2目标将失败,因为它找不到.NET的定义HttpUtility。 public string JavaScriptEncode(string input) { return HttpUtility.JavaScriptStringEncode(input); } 要解决此问题,我们需要添加对System.Web程序集的引用,但仅.NET 4.6.2目标需要它。为此,我们只需.csproj使用以下语法在文件中添加条件引用即可: 如果要有条件引用的NuGet程序包,则使用PackageReference。可以使用多个条件: 条件编译 有时我们可能想从某些目标的编译中排除某些C#文件。例如,以下是在NAudio中针对.NET 3.5目标的方法,我引用了System.Windows.Forms程序集,并从编译中排除了三个特定文件: posted @ 2020-10-21 01:52 N-COUNT 阅读(2605) 评论(0) 编辑 收藏 举报 会员力量,点亮园子希望 刷新页面返回顶部 公告 Copyright © 2024 N-COUNT Powered by .NET 8.0 on Kubernetes.NET 项目 SDK 概述 | Microsoft Learn
常用的 MSBuild 项目属性 - MSBuild | Microsoft Learn
理解 C# 项目 csproj 文件格式的本质和编译流程_csproj build 单独编译一个工程-CSDN博客
>
直接用2005打开网站,选中有代码那个文件夹就可以了:.Csproj文件学习笔记 - N-COUNT - 博客园