由于面向接口编程的关系,许多实现往往是动态注入运行,在一个项目中直接引用实现dll编译是不合理的。通常我们会在Post Build Event中添加一些xcopy命令将运行时才需要的dll复制到输出目录。在发布时会带来一些问题,比如:使用Visual Studio自带的Publish功能发布一个Web应用时就不会运行Post Build Event。同样的在基于TFS Build时也存在类似问题。
TFS Build时会根据对应Definition的名称创建两个子目录:Source、Binaries,Binaries下针对Web应用会创建发布目录"_PublishedWebsites",如果想要Post Build Event时将dll复制到对应目录下,最简单的方式就是再添加xcopy命令(这样的命令可能有多条),例如:
xcopy /y /i "$(SolutionDir)BuildEvents\Post-build" "$(TargetDir)_PublishedWebsites\$(TargetName)\bin\"
但是会给开发人员带来歧义、工作量并污染Post Build Event。其实我们想做的就是当MSBuild时的某一个参数值符合要求则执行发布用的命令(这个命令和Post Build Event执行的内容一样,就是$(TargetDir)不同),这时就需要修改项目文件来添加一些自定义的脚本实现该功能。首先在Build Definition的高级选项里添加MSBuild Arguments,例如:
/p:RMS=1
由于我的目标是和Release Management Service整合,故使用了该缩写。下面打开项目文件(csproj),开启AfterBuild,并添加一个Exec Task
<Target Name="AfterBuild"> <Exec Command="$(PostBuildEvent)" Condition=" ‘$(RMS)‘ == ‘1‘ " /> </Target>
上面的命令实际无法达到最终效果,这里自己绕了一个弯路。主要问题在于对PostBuildEvent的理解,其实它也是一个字符串变量,在执行时它内部使用的$(TargetDir)早已被替换,无法再重新计算结果。例如:
<Target Name="AfterBuild" Condition=" ‘$(RMS)‘ == ‘1‘ "> <PropertyGroup> <TargetDir>$(TargetDir)_PublishedWebsites\$(TargetName)\bin\</TargetDir> </PropertyGroup> <Message Text="$(TargetDir)" /> <Exec Command="$(PostBuildEvent)" /> </Target>
TargetDir的值确实产生变化,但PostBuildEvent的值也已经被提前计算,我们无法再让它被动态计算一次。幸好MSBuild 4.0以上版本允许我们使用一部分.NET代码来修改这些变量,我们只需调用System.String的Replace方法即可,参考如下:
<Target Name="AfterBuild"> <Exec Command="$(PostBuildEvent.Replace("$(TargetDir)", "$(TargetDir)_PublishedWebsites\$(TargetName)\bin\"))" Condition=" ‘$(RMS)‘ == ‘1‘ " /> </Target>
通过上面的方法就可以将Web应用完整发布,并结合Release Management Service实现持续集成。
原文:http://www.cnblogs.com/junchu25/p/4227408.html