本文重点介绍Windows下,在不调用外部工具的前提下,对目标文件和相关的资源文件进行打包。
Windows鸡肋的命令行使得 VS 构建后的打包发布很是头疼,最简单的打包也没有内建命令,更没类似于 Java 下 Maven 的助攻。唯一找到的 .NET MAVEN PLUGIN 还需要依赖 dotnet core 这个外援,惨呐惨!
如果需要在 build 完成后做一些打包之类的处理,一种方式是在 VS 的 post-build 中编写脚本,另外一种方式是使用 MSBuild Community Tasks 这个 Nuget 包,Github 地址:https://github.com/loresoft/msbuildtasks。MSBuild Community Tasks是一个开源的封装了MSBuild Task的库,支持诸如FTP上传,发送邮件,移动文件,运行NUnit测试,Svn操作,Zip压缩及解压缩等,详细支持的Task详见官方文档:Community Tasks 。
Zip 打包
当前目录结构如下:
| Hello.csproj
| packages.config
| Hello.sln
├─bin
│ ├─Debug
│ └─Release
├─obj
├─packages
│ └─MSBuildTasks.1.5.0.235
│ │ MSBuildTasks.1.5.0.235.nupkg
│ │
│ ├─build
│ │ MSBuildTasks.targets
│ │
│ └─tools
│ MSBuild.Community.Tasks.dll
│ MSBuild.Community.Tasks.Targets
│ MSBuild.Community.Tasks.xml
│ MSBuild.Community.Tasks.xsd
│
├─scripts
│ │ Web.config
│ ├─includes
│ │ advanced.html
│ ├─src
│ │ createTestFiles.txt
│ ├─testfiles
│ │ image.png
│ └─ui
│ ├─images
│ │ icon.png
│ └─js
│ jquery.js
└─src
HellowWord.cs
安装 MSBuild Community Tasks
安装方式参考官方文档。安装完 MSBuild Community Tasks 之后,packages.config 中会多出一条配置信息:
<package id="MSBuildTasks" version="1.5.0.235" targetFramework="net461" developmentDependency="true" />
同时 Hello.csproj 会增加如下信息:
<Import Project="packages\MSBuildTasks.1.5.0.235\build\MSBuildTasks.targets" Condition="Exists('packages\MSBuildTasks.1.5.0.235\build\MSBuildTasks.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\MSBuildTasks.1.5.0.235\build\MSBuildTasks.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\MSBuildTasks.1.5.0.235\build\MSBuildTasks.targets'))" />
</Target>
在上述配置后面追加打包的配置,例如:
<!-- Release模式下构建成功后后执行 -->
<Target Name="AfterBuild" Condition="'$(Configuration)'=='Release'">
<ItemGroup>
<!-- ZipFiles 需要打包的文件,可以定义多个 ZipFiles -->
<ZipFiles Include="kits\$(ProjectName)" />
<!-- 定义一个ItemGroup方便后续拷贝。 **\*.*: 递归拷贝目录下所有的文件 -->
<ScriptFiles Include="scripts\**\*.*" />
</ItemGroup>
<!-- 删除(清空)临时目录,RemoveDir是VS的一个Task -->
<RemoveDir Directories="@(ZipFiles)" />
<!-- 将scripts下的所有文件拷贝到 kits\$(ProjectName) 目录下,并保持目录结构。 -->
<!-- %(RecursiveDir)%(Filename)%(Extension):拷贝文件时保持其目录结构 -->
<!-- 如果不需要保持目录结构,只拷贝文件,将 DestinationFiles 替换成 DestinationFolder。-->
<Copy SourceFiles="@(ScriptFiles)" DestinationFiles="@(ScriptFiles->'kits\$(ProjectName)\%(RecursiveDir)%(Filename)%(Extension)')" />
<Copy SourceFiles="$(TargetPath)" DestinationFolder="kits\$(ProjectName)\lib" />
<!-- 调用 Zip task 进行打包 -->
<!-- Flatten="True",只打包文件,不保留目录结构-->
<!-- Flatten="False" 保留目录结构,目录是以 WorkingDirectory 为相对目录 -->
<Zip ZipFileName="kits\$(ProjectName).zip" WorkingDirectory="kits" Files="@(ZipFiles)" Flatten="False" Quiet="true" />
<RemoveDir Directories="@(ZipFiles)" />
</Target>
在 Release 模式下构建成功后,将生成的目标文件和scripts目录下的所有文件打包到 kits/Hello.zip 文件中,并保持目录结构,zip中文件结构
Hello
| Web.config
├─lib
│ Hello.dll
├─includes
│ advanced.html
├─src
│ createTestFiles.txt
├─testfiles
│ image.png
└─ui
├─images
│ icon.png
└─js
jquery.js
Reference
Zip 参考:
Task参考:
Other Example: