Visual Studio 2017 以前的旧格式的 csproj Import 进来的 targets 文件有时不能正确计算属性(PropertyGroup)和集合(ItemGroup)
我在之前的博客中有教大家如何编写 NuGet 工具包,其中就有编写 .targets 文件。
我在实际的使用中,发现 Visual Studio 2017 带来的含 Sdk 的新 csproj 格式基本上没有多少坑;然而旧的 csproj 文件却总是不能完美的运行,总是出错。关键是,不是每台电脑都出错,不是每个时机都出错。
本文将讲一些坑。
本文的前置知识
你可能需要了解 csproj 文件的格式和编译过程,才可能读懂本文,所以需要先阅读:
问题
下面的代码来自 SourceFusion 项目的早期版本。
这是一个 .targets 文件,项目安装此 NuGet 包之后就会自动 Import 这个 targets 文件。
<Project>
<PropertyGroup>
<_DefaultSourceFusionWorkingFolder Condition="'$(_DefaultSourceFusionWorkingFolder)' == ''">obj\$(Configuration)\</_DefaultSourceFusionWorkingFolder>
<SourceFusionWorkingFolder Condition="'$(SourceFusionWorkingFolder)' == ''">$(_DefaultSourceFusionWorkingFolder)</SourceFusionWorkingFolder>
<SourceFusionToolsFolder>$(SourceFusionWorkingFolder)SourceFusion.Tools\</SourceFusionToolsFolder>
<SourceFusionGeneratedCodeFolder>$(SourceFusionWorkingFolder)SourceFusion.GeneratedCodes\</SourceFusionGeneratedCodeFolder>
</PropertyGroup>
<Target Name="_SourceFusionCreateDirectories" BeforeTargets="_SourceFusionWriteCompilingArgs;_SourceFusionWriteFilterArgs">
<ItemGroup>
<SourceFusionDirectory Include="$(SourceFusionWorkingFolder)" />
<SourceFusionDirectory Include="$(SourceFusionToolsFolder)" />
<SourceFusionDirectory Include="$(SourceFusionGeneratedCodeFolder)" />
</ItemGroup>
<MakeDir Directories="@(SourceFusionDirectory)" ContinueOnError="false" />
</Target>
</Project>
代码的解读如下:
- 创建了一个私有属性
_DefaultSourceFusionWorkingFolder,三个公有属性SourceFusionWorkingFolder、SourceFusionToolsFolder、SourceFusionGeneratedCodeFolder。 - 在编译期间,执行一个私有的 Target,收集所有收集到的文件夹,形成一个
SourceFusionDirectory集合。然后将集合中的所有字符串视为文件夹,创建这几个文件夹。
在新的有 Sdk 的 csproj 中,这个 targets 文件的执行没有问题。但是,对于旧的 csproj 来说,就经常出现这几个属性为空或者部分为空的情况。额外的,就算修改这个文件,上面的属性也不会生效。
不过,如果使用命令行进行编译,这个却又是生效的。
原因
究其原因,这是 MSBuild 对项目文件(csproj)的解析和 Visual Studio 对项目文件的解析是不同的。命令行使用的是 MSBuild 解析 csproj,而 Visual Studio 使用的是 VSProjectSystem。
对于 VSProjectSystem 来说,Project 根节点下的 PropertyGroup 和 ItemGroup 对不会更新。有时清除 Visual Studio 的项目缓存可以解决这个问题,但有时清除也不能解决。
真实的原因我并没有调查出来。但以上代码在大多数开发者的 Visual Studio 中是可以正常使用的,但有少数开发者使用这个会出现错误(没有创建任何文件夹)。
解决办法
既然问题出在 MSBuild 和 VSProjectSystem 对属性和集合处理的不同,那么我就不要创建动态的集合,而是在 Target 内部编写属性和集合。
在 Target 内部的属性和集合将在编译期间进行计算,而不是在 Visual Studio 打开的时候就计算好。于是我们每次编译的时候都可以获得最新的属性和集合的值。
衍生知识
旧格式的 csproj 是不会自动计算属性和集合的变更的,这也是为什么项目文件改变的时候,Visual Studio 需要重新加载项目才可以正常显示和编译项目。同时,如果编辑旧格式的 csproj 文件,也需要先卸载掉项目才可以。而新格式的 csproj 是可以直接编辑而不需要卸载项目的,同时如果被外部改变,也不需要重新加载项目,而是可以直接计算出来新的属性和集合。
Visual Studio 2017 以前的旧格式的 csproj Import 进来的 targets 文件有时不能正确计算属性(PropertyGroup)和集合(ItemGroup)的更多相关文章
- 用于Azure功能的Visual Studio 2017工具
今天我们很高兴地宣布发布第一个预览的Visual Studio 2017工具的Azure功能.这个预览介绍了一些令人兴奋的变化,我们以前的版本.此外,除了支持Visual Studio 2017之外, ...
- Visual Studio 2017 怎么将自动生成属性设置为旧版格式
工具:Visual Studio 2017 1.点击工具,进入选项 2.选项窗口左侧找到C#--代码样式,点击 3.找到表达式首选项中:使用属性的表达式主体.使用索引器的表达式主体和使用访问器的表达式 ...
- 最强 IDE Visual Studio 2017 正式版发布
Visual Studio 2017 正式版发布,该版本不仅添加了实时单元测试.实时架构依赖关系验证等新特性,还对许多实用功能进行了改进,如代码导航.IntelliSense.重构.代码修复和调试等等 ...
- Visual Studio 2017正式版发布全纪录
又是一年发布季,微软借着Visual Studio品牌20周年之际,于美国太平洋时间2017年3月7日9点召开发布会议,宣布正式发布新一代开发利器Visual Studio 2017.同时发布的还有 ...
- Visual Studio 2017开发环境的安装
Visual Studio 2017是微软为了配合.NET战略推出的IDE开发环境,同时也是目前开发C#程序最新的工具,本节以Visual Studio 2017社区版的安装为例讲解具体的安装步骤. ...
- Visual Studio 2017 Enterprise (15.3)
版本15.3更新在用户离线下载时更加人性化,包含了进度显示,下载出错可以输入R,进行下载的重新尝试,并在当前下载框下继续下载为完成的作业,结合 --layout 参数的离线文件的检查和修复,并且在下载 ...
- Visual Studio 2017 发布 15.5 版本,百度网盘离线安装包下载。
Visual Studio 2017 15.5 版本已正式发布,同时发布的还有 Visual Studio for Mac 7.3 .此次更新包含主要性能改进,新特性以及 bug 修复.发行说明中文版 ...
- Visual Studio 2017 Enterprise 发布 15.4 版本,离线安装包百度网盘下载。
Visual Studio 2017 于2017年10月13日发布 15.4 版本.该版本包含多项生产力改进,支持 .NET Standard 2.0 ,并且可以开启 Xamarin Live Pla ...
- Visual Studio 2017 Enterprise 发布 15.3.3 版,附离线安装包百度网盘下载。
Visual Studio 2017 Enterprise 发布 15.3.3 版,附离线安装包百度网盘下载. Visual Studio 2017 Enterprise 更新至 15.3.3 ,本安 ...
随机推荐
- NeteaseCloudWebApp模仿网易云音乐的vue自己从开源代码中学习到的
github地址: https://github.com/javaSwing/NeteaseCloudWebApp 1.Vue.prototype.$http = Axios // 类似于vue-re ...
- 各个安卓版本 使用的 Linux Kernel Version
Android Version |API Level |Linux Kernel in AOSP --------------------------------------------------- ...
- initctl 创建自己的JOB
我们的项目需要一个启动一个外部的Jetty server.发现每次kill了这个jetty的进程后,系统会自动启动一个jetty.追查下去发现,原来是在/etc/init.d/jetty 脚本的sta ...
- English trip -- VC(情景课) 6 C Is your class at 11:00? 你的课11点开始吗?
Grammar focus 语法点 Is your class at 11:00 ? # 带be动词的一般疑问句 Yes, it is No, it isn't 相当于 is not Pra ...
- dubbo监控报错Error creating bean with name 'uriBrokerService'
在jdk1.8下面会出现此错误 解决方法: 1.更换服务器jdk版本.(会影响其他项目环境) 2.修改dubbo-admin tomcat默认jdk版本. 3.修改dubbo-admin项目依赖(de ...
- vijos 1423 最短路or环(有向图)
最佳路线 描述 年久失修的赛道令国际汽联十分不满.汽联命令主办方立即对赛道进行调整,否则将取消其主办权.主办方当然必须马上开始行动. 赛道测评人员经过了三天三夜的数据采集,选出了若干可以使用的道路和各 ...
- CodeForces 558B
Description Amr has got a large array of size n. Amr doesn't like large arrays so he intends to make ...
- Xshell如何设置,当连接断开时保留Session,保留原文字
Xshell [1] 是一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议.Xshell 通过互联网到远程主机的安全连接以及它 ...
- HDU 3720 深搜 枚举
DES:从23个队员中选出4—4—2—1共4种11人来组成比赛队伍.给出每个人对每个职位的能力值.给出m组人在一起时会产生的附加效果.问你整场比赛人员的能力和最高是多少. 用深搜暴力枚举每种类型的人选 ...
- pyqt(二) 创建第一个程序(helloworld)解决object has no attribute 'setCentralWidget'
1.运行Qt Creator QtCreator主界面分为了6个模式:欢迎模式.编辑模式.设计模式.Debug调试模式.项目模式和帮助模式,分别由左侧的6个图标进行切换,对应的快捷键是Ctrl + 数 ...