本主题的目标是通过对XAF 源码的重新编译再到重新分包部署来学习、理解MSBuild的一些常用用法。
为什么用XAF来学习呢,最重要的原因是我正在使用它。而且对于重新编译XAF的工作看上去不是玩具,而且在实际的使用当中真正能用得上。
XAF是什么,如果你熟悉他那正好,如果你还不太清楚,你可以在园内搜索一下。为了不偏离主题,在此不做过多的介绍,这不是很影响下面的讨论。要是能用简单的几句话描述那就是:XAF是一个优秀的企业级应用程序框架。你只需要负责处理实际的业务逻辑。框架会自动为你生成数据库(使用XAF中的orm工具XPO)。框架还可以为你生成非常强大的UI展现层(其中用到DEVExPress套件)。听起来像是神话,当你潜心研究开源项目的时候不妨看看他,虽然这是一个商业的产品。但是当你真正看到他的强大的时候,你就会不由的感叹,什么是城乡差距。呵呵,无意贬低开源项目,必定侧重点不同。
在详细的说明一下本主题的议题。当你安装了XAF的源码包之后,你可能想通过单步调试来监测一下到底XAF为你做了一些什么,但是调试器没有本法追踪到DLL内部的源代码。这时你需要重新编译源码包使调试器便能追踪到DLL内部的源码。(看XAF的源码也是一件即令人兴奋又令人沮丧的事情)。用VS编译项目的时候会在BIN目录生成一个和DLL文件同名但以.pdb为后缀名的文件。当启用调试的时候调试器会通过这个文件找到相应的程序源码。完整的XAF源码包大概包含80多类项目至少要生成100个以上的DLL文件。也许在你的项目里面实际用不了这么多。这些DLL互相引用,如果要手工去建立解决方案,然后添加引用,无疑是一件很耗时又令人苦恼的事情。令人欣慰的是官方为我们提供了编译脚本。其实就是运用了MSBuild,gacutil 的一些批处理文件。
我们先来看看devexpress官方对于重新编译的一些指南。
以下是简单的描述:
1、先使用它的安装包安装组件。
2、用SN工具生成你自己的强命名文件,将其拷贝到指定目录。
3、找到安装目录下的所有的DLL文件删除它们。运行脚本清除devexpress(GAC)全局程序集缓存.
4、在源码目录运行编译脚本。
5、在工具箱注册组件。
(注意:如果你的源码包不是完整的,就不能删除部分DLL)
几个步骤里涉及到了多个非常重要的知识点,和几个似乎不太常用的几个工具。
1、强名称程序集和Sn.exe工具
强名称主要是一些大公司为了用于程序集的统一命名,另一个目的是使程序集无法伪造。但是 Richard Grime介绍了一种方法可以在某种程度上破解强名称(http://grimes.demon.co.uk/workshops/fusionwscrackthree.htm)开始是基于CLR1.1版本的一个Bug.微软在.net2.0中修复了这个bug,随后Richard Grime
又在他的文中补充了2.0/3.0版本强名称的破解方法。但事实上最牛X的Cracker来自中国,dev的注册程序几乎是和官方同步更新(Danny 我们都很期待你的文章,希望能有幸看到)。当你引用一个第3方的控件的时候,强名称有可能会给你带来一些麻烦。但实际上强名称并不是主要用来解决安全问题。如果你编写控件,那么给你的项目加一个强命名就是必须的,只有拥有强名称的程序集才能够放入到GAC中。只有放入到GAC中的程序集才能够在VS的工具箱中被引用。所以控件、和组件必须使用强名称。
强名称使用Sn.exe命令行工具来创建。当然也可以使用vs项目属性--签名的可视化工具生成。
一般常用的类似以下命令。
使用命令行又是要比VS方便。接下来我们到D盘把我们刚刚生成的私钥文件拷贝到DevExpress.Key\文件夹下。
2、XCopy与GAC
接下来要做的事情是删除Dll文件,和清除dev组件的GAC.
.NET程序集的部署通常有两种策略。 我喜欢是XCOPY部署,不用访问注册表,不访问window活动目录。比那些乱七八糟的绿色版软件都干净。即使用MSI安装服务都很干净。(有一天我偶然发现,所谓的绿色版软件就是一个批处理文件用来写注册表,在卸载的时候就算删了文件夹,还是会给注册表留下了垃圾,通常这个批处理也会篡改你的主页)
既然XCopy那么好用为什么还需要GAC呢,我觉得这个微软自家最需要了,微软为了让自己的操作系统原生态的支持.net各个版本号的程序集而设计的。比如:如果你的web应用程序如果是在2.0环境下开发的,你的程序就会引用GAC中的2.0相应的程序集DLL。如果是3.5的, 你的程序就会引用3.5 的版本。像对dev这样的频繁更换产品版本的公司也是极受用的。还有可能是对于性能上的考虑吧。但对于大多数的企业应用来说文件夹部署更实用一些。
我们要如何查看并清除GAC里的DLL呢?当我们在安装.net平台的时候会自动的安装一个名为shfusion.dll的外壳扩展,它可以使我们在资源管理器里浏览GAC文件夹,通常情况下我们可以当他不存在。不要试图在这种情况下修改GAC.若要修改GAC文件夹需要用到.net提供的GACUtil.exe工具。要卸载GAC程序集MSDN提供了两种方式。
使用 Windows 界面
导航到位于 %systemdrive%\Windows\Assembly 的 GAC。
右键单击在您的应用程序中包括的每个程序集文件,单击“卸载”,然后单击“是”进行确认。
使用命令行
按以下方法打开 Visual Studio 命令提示符:单击“开始”,依次指向“所有程序”、Microsoft Visual Studio 2008、“工具”,然后单击“Visual Studio 2008 命令提示”。
在命令提示符下键入以下命令: gacutil /u <完全限定的程序集名称> 在此命令中,程序集名称是要从 GAC 中卸载的程序集的名称。 下面的示例从 GAC 中移除名为 hello.dll 的程序集。 gacutil /u "hello,Version=1.0.0.0, Culture=neutral, PublicKeyToken=0123456789ABCDE
dev的脚本中使用了另一种更直接的方式。这可能需要你要有计算机管理员权限。
rd /s /q %GACPATH%DevExpress.Data.%dxver%
rd /s /q %GACPATH%DevExpress.Data.%dxver%.Linq
rd /s /q %GACPATH%DevExpress.Design.%dxver%
%GACPATH%代表全局缓存目录,可以用命令行工具直接清除目录树。如果你用命令行工具进入全局缓存目录,你会发现所有的dll实际上也是一个目录
这样就可以编写批处理来卸载GAC程序集。
3、MSBuild与MSBuild.exe工具
MSBuild是一个相对大的概念,旨在统一以往的各种编译技术,它是一种特有的XML格式。VS所生成的.Proj、CSproj、vbproj等文件都是以MSbuild XML 格式撰写的。更多的信息请参阅MSDN.
在编译XAF的过程中用到了MSBuild.exe工具的脚本只有一句(里面用到了一些替代符如 :%configuration%=Debug)
%msbuild% /nologo /t:Rebuild /verbosity:quiet /p:Configuration=%configuration%;Platform=AnyCPU
他将自动查找目标完成我们的生成工作。这个过程可能需要一段时间。
4、用gacutil注册程序集
之后要把成生成的dll注册到GAC中,这时用到 gacutil工具
gacutil.exe 工具有很多参数。常用的命令如下:
gacutil /i mydll.dll
dev的部分脚本
cd DevExpress.Dll
%gacutil% -i DevExpress.BonusSkins.%DXVER%.dll
%gacutil% -i DevExpress.Data.%DXVER%.Compact.dll
%gacutil% -i DevExpress.Data.%DXVER%.dll
%gacutil% -i DevExpress.OfficeSkins.%DXVER%.dll
%gacutil% -i DevExpress.Tutorials.%DXVER%.dll
%gacutil% -i DevExpress.Utils.%DXVER%.dll
%gacutil% -i DevExpress.Web.ASPxEditors.%DXVER%.dll
%gacutil% -i DevExpress.Web.ASPxGridView.%DXVER%.dll
%gacutil% -i DevExpress.Web.ASPxGridView.%DXVER%.Export.dll
执行dev的脚本,所有的dll将被加载到GAC中。至此,我们再用dev的工具箱组册工具注册生成的dll 编译就此结束。
接下来的工作是我想把重新编译过像项目再重新打包,以方便分发给同事一起使用,我将在细致看过MSI\CAB\XCOPY\Clickonce和NTD这几种部署方法,之后选择一种合适的方法。