title author date CreateTime categories
Roslyn 如何使用 MSBuild Copy 复制文件
lindexi
2018-12-25 9:35:8 +0800
2018-07-10 10:23:15 +0800
Roslyn MSBuild 编译器

本文告诉大家如何在 MSBuild 里使用 Copy 复制文件

需要知道 Rosyln 是 MSBuild 的 dotnet core 版本。

在 MSBuild 里可以使用很多命令,本文告诉大家如何使用 Copy 这个 Task 来复制文件

在开始本文之前,希望大家已经知道了一些关于 csproj 文件格式,如果还是不知道,请看理解 C# 项目 csproj 文件格式的本质和编译流程 - walterlv

最简单的复制命令请看代码

  <Copy SourceFiles="lindexi.txt" DestinationFolder="LetirNuhe\" ></Copy>

需要注意,不要把 Copy 直接写在 Project 下,如下面的代码

<Project Sdk="Microsoft.NET.Sdk">
<!-- 忽略代码 -->
<Copy SourceFiles="lindexi.txt" DestinationFolder="LetirNuhe\" ></Copy>
</Project>

就会出现下面异常

D:\林德熙\代码\测试代码\CemfeetoQewasXaiki\CemfeetoQewasXaiki.csproj : error  : 无法识别元素 <Project> 下面的元素 <Copy>。  D:\林德熙\代码\测试代码\CemfeetoQewasXaiki

为了运行 Copy 需要使用下面代码


<Target Name="Copy" BeforeTargets="CoreCompile">
<Copy SourceFiles="LekeexelSurgooHerkassayyayTowjome.txt" DestinationFolder="LetirNuhe\"></Copy>
</Target>

需要知道 Target 需要给 Name 并且告诉他在什么时候运行,这里使用 BeforeTargets 告诉在开始编译前,也就是复制的文件会被编译。

对于复制资源文件或需要编译的资源,就设置 BeforeTargets 在编译前,如果是不需要进行编译的文件,如 dll 就可以设置在编译后运行。

重新生成项目,可以看到文件夹存在文件

如果刚才没有创建 文件,复制时找不到文件,就会出现在重新编译出现无法编译

error MSB3030: 无法复制文件“lindexi.txt”,原因是找不到该文件

复制有多个方式,下面让我来一个个和大家说

文件到文件

第一个方法是最简单的,复制文件到文件

例如我需要复制 lindiexi.txt 到 LetirNuhe\lindexi ,可以使用下面代码

  <Target Name="Copy" BeforeTargets="CoreCompile">
<Copy SourceFiles="lindexi.txt" DestinationFiles="LetirNuhe\lindexi.txt"></Copy>
</Target>

那么如果需要复制多个文件到多个文件?

可以看到 SourceFiles 是可以输入多个文件,只需要使用;作为多个文件

下面复制 lindexi.txtlindexi.gitee.io.txtLetirNuhe 文件夹下

  <Target Name="Copy" BeforeTargets="CoreCompile">
<Copy SourceFiles="lindexi.txt;lindexi.gitee.io.txt" DestinationFiles="LetirNuhe\lindexi.txt;LetirNuhe\lindexi.gitee.io.txt"></Copy>
</Target>

这里的文件是对应的,也就是第一个文件是 lindexi.txt在 DestinationFiles 也需要写第一个文件是lindexi.txt的,如果写为lindexi2.txt 会自动把 lindexi.txt 复制并且修改名字。第一个文件对应 DestinationFiles 写的第一个文件,也就是项对应。

因为从文件复制到文件的代码太多了,如果只是需要把文件都放在相同的文件夹,可以使用下面的方法

文件到文件夹

如果需要把文件都复制到相同的文件夹,可以使用下面代码

  <Target Name="Copy" BeforeTargets="CoreCompile">
<Copy SourceFiles="lindexi.txt;lindexi.gitee.io.txt" DestinationFolder="LetirNuhe\"></Copy>
</Target>

使用 DestinationFolder 指定文件夹,在文件夹不存在的时候会自动创建,刚才的代码也是。

文件列表到文件夹

实际上刚才是写 SourceFiles ,但是实际这样写无法使用通配,也就是*.txt的方法,如果需要使用就需要用文件列表

  <ItemGroup>
<Txt Include="*.txt"></Txt>
</ItemGroup> <Target Name="Copy" BeforeTargets="CoreCompile">
<Copy SourceFiles="@(Txt)" DestinationFolder="LetirNuhe\"></Copy>
</Target>

多个文件的列表是在 ItemGroup 里添加 一个新的标签,这个标签是可以自己定义名字的,我这里定义了 Txt ,让他包含了 *.txt ,现在就可以在 SourceFiles 使用。使用数组的方法是 @(Txt) ,通过 @ 和 标签名就可以拿到标签的文件。如果这时输出@(Txt) 会看到下面代码

xx\lindexi.txt;xx\lindexi.gitee.io.txt

因为 ItemGroup 可以写多个标签,可以修改下面代码

  <ItemGroup>
<Txt Include="lindexi.txt"></Txt>
<Txt Include="lindexi.gitee.io.txt"></Txt>
</ItemGroup> <Target Name="Copy" BeforeTargets="CoreCompile">
<Copy SourceFiles="@(Txt)" DestinationFolder="LetirNuhe\"></Copy>
</Target>

较新才复制

如果不想每次编译都复制,可以设置SkipUnchangedFiles="True" 只有在发现文件较新才复制。

判断文件较新使用的是判断两个文件的最后更改时间和文件大小。

软连接

可以通过设置 UseHardlinksIfPossible="True"不复制文件,而是设置文件的软连接,也就是修改一个文件可以两个地方生效

设置软连接可以做到在多个项目看起来都有自己的文件,但是实际都是指向相同的文件

需要说的是,这个是软连接,但是在系统是硬连接方式。

判断文件存在就不复制

如果需要判断文件存在就不复制,可以使用 Condition 判断

    <Copy SourceFiles="@(Txt)" DestinationFolder="LetirNuhe\" SkipUnchangedFiles="True" OverwriteReadOnlyFiles="True" Condition="!Exists('LetirNuhe\lindexi.txt')"></Copy>

通过 Exists 判断文件是否存在,如果存在就不复制。

更多 MSBuild 相关博客请看

理解 C# 项目 csproj 文件格式的本质和编译流程 - walterlv

如何创建一个基于命令行工具的跨平台的 NuGet 工具包 - walterlv

如何使用 MSBuild Target(Exec)中的控制台输出 - walterlv

更多关于 Roslyn 请看 手把手教你写 Roslyn 修改编译

参见:Roslyn 入门 - CSDN博客

2018-12-25-Roslyn-如何使用-MSBuild-Copy-复制文件的更多相关文章

  1. Roslyn 如何使用 MSBuild Copy 复制文件

    本文告诉大家如何在 MSBuild 里使用 Copy 复制文件 需要知道 Rosyln 是 MSBuild 的 dotnet core 版本. 在 MSBuild 里可以使用很多命令,本文告诉大家如何 ...

  2. TDirectory.Copy复制文件

    描述:复制文件夹以及文件夹下的内容 procedure Copy(const SourceDirName, DestDirName: string) 参数一:源文件夹 参数二:目标文件夹 所在单元:S ...

  3. 2018.12.25 SOW

    1. Understanding Customer Requirements 11.1. Project Overview 21.2. System Requirements 21.3. Indust ...

  4. 2018.12.25 Spring中JDBCTemplate模版API学习

    1 Spring整合JDBC模版 1.1 spring中土拱了一个可以操作数据库的对象.对象封装了jdbc技术 JDBCTemplateJDBC模板对象 1.2 与DBUtils中的QueryRunn ...

  5. Linux命令:cp (copy)复制文件或目录

    复制文件,只有源文件较目的文件的修改时间新时,才复制文件     cp -u -v file1 file2 .将文件file1复制成文件file2     cp file1 file2 .采用交互方式 ...

  6. 12.25模拟赛T1

    可以区间dp,但是复杂度太高. 所以应该是贪心,怎么贪心呢? 这种题目,最好还是手玩找一些规律. 可以发现,由于保证可以m次填完,所以颜色之间没有相互包含关系. 比较像分治的模型. 所以考虑拿到一个区 ...

  7. loli的测试-2018.12.9

    模拟赛-2018.12.9 这是NOIP之后第一次模拟赛...但是考的比较悲惨. 非常喜欢写考试总结,不知道为什么... T1:https://www.luogu.org/problemnew/sho ...

  8. 2018.12.02 Socket编程之初识Socket

    Socket编程主要分为TCP/UDP/SCTP三种,每一种都有各自的优点,所以会根据实际情况决定选用何种Socket,今天开始我将会逐步学习Socket编程,并将学习过程记录于此. 今天学习的是TC ...

  9. OPPO Developers Conference(2018.12.26)

    时间:2018.12.26地点:北京国家会议中心

  10. Tencent Cloud Developers Conference(2018.12.15)

    时间:2018.12.15地点:北京朝阳悠唐皇冠假日酒店

随机推荐

  1. HBase+Redis

  2. 【NOIP2016提高A组集训第14场11.12】随机游走——期望+树形DP

    好久没有写过题解了--现在感觉以前的题解弱爆了,还有这么多访问量-- 没有考虑别人的感受,没有放描述.代码,题解也写得歪歪扭扭. 并且我要强烈谴责某些写题解的代码不打注释的人,像天书那样,不是写给普通 ...

  3. 错误 2 error C2059: 语法错误:“::”

    设置项目属性,在预定义处理器中添加定义NOMINMAX来禁止使用Vsual C++的min/max宏定义. 项目属性   ——> C/C++ ——> 预处理器 ——> 预处理器定义 ...

  4. 19-10-26-F

    ZJ一下: T1码了暴力但是并没有开出来身高的神奇性质…… T2打模拟,但是只摸了卅分 T3不会,码了一个测试点分治.10分 TJ一下: T1. 发现身高范围在$[140,200]$时,直接去重跑$\ ...

  5. python基础---递归函数真题解析

    方法一.有如下值集合 [11,22,33,44,55,66,77,88,99,90...],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中. 即: {'k ...

  6. Python技巧—list与字符串互相转换

    Python技巧-list与字符串互相转换 在Python的编程中,经常会涉及到字符串与list之间的转换问题,下面就将两者之间的转换做一个梳理. 1.list转换成字符串 命令:list() 例子: ...

  7. 编码格式简介(ANSI、GBK、GB2312、UTF-8、UTF-16、GB18030和 UNICODE)

    很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物,他们把这称为”字节”.再后来,他们又做了一些可以处理这些字节的机器,机器开动了,可以用字节来组合出很多状态 ...

  8. PAT甲级——A1049 Counting Ones

    The task is simple: given any positive integer N, you are supposed to count the total number of 1's ...

  9. CentOS 6.5 Apache、MySQL、PHP环境配置(LAMP)

    yum -y install httpd mysql-server php #安装apache.mysql和PHP yum -y install php-mysql php-gd php-mbstri ...

  10. 关于Cocos2d-x多线程异步载入资源的问题

    我们通常使用CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("xxx.plist" ...