下载连接:http://download.csdn.net/source/237101
企业服务(Com+)作为一项重要的企业级编程,配置比较麻烦,需要手动执行很多操作,所以我以一个用com+实现的跨进程缓存为例子,展示怎么使用InstallUtil和PostBuild事件自动完成这些工作,并提供给大家一个企业服务项目模版,方便大家使用,大家用这个模版项目,往里面放上自己的逻辑,就可以直接使用了(这里要多谢蝈蝈的努力,这是他对从com+的一些文章http://beta.joycode.com/ghj/category/1320.aspx,大家可以参考)
解决方案里有三个项目,一个服务端(ComPlusServerTemplate),一个客户端(ClientTemplate),一个公共组件(Component),实现了一个简单的进程独立的缓存,展示了
- COM+简单调用
- 传递自定义参数
- 实现跨进程单件
我大概讲解一下利用.Net工具InstallUil,和Visual Studio的编译事件自动话安装企业服务的方法,由于下载的代码里面都有详细注释,具体大家自己下了看,我不再赘述,我在这里只是点出一些关键的地方.在以后的篇幅里,我会介绍怎样传递自定义参数,用Com+来实现跨进程的单件,以及怎样调试Com+.
怎样使用InstallUtil.exe自定义企业服务安装:
安装企业服务需要做两件事情,一把所有引用的程序集放入GAC,然后把自己注册为企业服务
手动的话,一般编译完成后我们利用visual studio带的工具gacutil来注册到GAC,而后利用regsvc来完成注册过程
其实.Net自己带了一个InstallUtil.exe,可以用来帮助大家通过程序完成上面的工作
我先简单介绍一下他的工作原理,这个工具可以迅速安装服务应用程序,最重要的是,他可以程序集中的自定义的安装组件来安装Com+,详见MSDN:http://www.msdn.net/library/chs/default.asp?url=/library/CHS/cptools/html/cpconinstallerutilityinstallutilexe.asp
安装组件必须从System.Configuration.Install.Installer继承,需要引用程序集System.Configuration.Install,通过重载Installer的Install和UnInstall方法件里我们就可以实现自定义安装和卸载
我们来看看Install方法中主要的安装代码:(封装在了InstallHelper里)
//取得当前Assembly,注意这个Assembly就是我们要安装的Assembly,因为Installer就包含在这个Assembly里面 Assembly currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
string assemblyFullPath = GetAssemblyFullPath(currentAssembly.Location);
string assemblyName = Path.GetFileName(currentAssembly.Location);
Publish publisher = new Publish();
//把自己放入GAC publisher.GacInstall(assemblyFullPath);
/*把引用的程序集放入GAC,
* 需要说明的是不是所有引用的程序集都需要放入GAC,只有那些确实在运行中用到的才用,比如
* 我在这里排除了Interop.COMAdmin程序集,因为他只在安装中会用到,实际运行时不会用到,
* 这个东西的用处后面会讲到,当然,你还可以扩展一下这个程序,让需要用到的程序集从配置文件里读出
*/ Assembly ass; foreach (AssemblyName assName in currentAssembly.GetReferencedAssemblies())
{
ass = System.Reflection.Assembly.Load(assName);
if (!ass.GlobalAssemblyCache && assName.Name != "Interop.COMAdmin")
{
MessageBox.Show(string.Format("Assembly \"{0}\" has been loaded into GAC ",assName.FullName));
publisher.GacInstall(GetAssemblyFullPath(ass.Location));
}
}
// 把自己安装为企业服务 string ApplicationName = InstallComponent(stateSaver, assemblyName, assemblyFullPath, installObject);
// 下面是把企业服务设为一直运行,默认当企业服务空闲时会停止,这里用到了COMAdmin这个组件来实现
//他的功能十分强大,具体用法参见http://blog.joycode.com/ghj/archive/2006/12/08/88733.aspx COMAdmin.COMAdminCatalog ca = new COMAdmin.COMAdminCatalogClass();
COMAdmin.COMAdminCatalogCollection cacc = (COMAdmin.COMAdminCatalogCollection)ca.GetCollection("Applications");
cacc.Populate();
foreach (COMAdmin.COMAdminCatalogObject cac in cacc)
{
if (cac.Name.ToString() == ApplicationName)
{
cac.set_Value("RunForever", true);
cacc.SaveChanges();
break;
}
}
安装企业服务的时候,我们调用了InstallComponent方法,在这个方法里具体实现了企业服务的安装,在这个函数里面,注意这个语句
/*Com+的运行时目录是在系统目录里,所以程序集要用到的配置文件可能访问不到(当然不能把配置文件考过去,不信你可以试试)
* 所以我们需要配置他的应用程序根目录,让Com+仍然能正常的访问配置信息,由于服务器系统不同,不是所有的服务器都支持
* 这个属性,所以ComPlusHasApplicationRootDirectory()包含了对系统是否支持此属性的判断
*/ if (ComPlusHasApplicationRootDirectory())
{
regConfig.ApplicationRootDirectory = Path.GetDirectoryName(assemblyFullPath);
}
注:操作系统判断参见http://www.cnblogs.com/yizhu2000/archive/2007/08/26/870666.html
怎样使用编译事件来完成自动安装
在项目的PostBuild事件中插入对InstallUtil的调用,在项目属性中找到BuildEvent页,在这里我们可以定义项目编译前后的动作
<图1>
点选EditPostBuildEvent,我们就可以编辑编译后希望执行的CommandLine了.注意在这里有很多vs定义号的宏可以使用,我们通过点击编辑窗体下面的macro按钮看到这些宏代表的具体内容
<图2>
主要代码如下
cd "$(TargetDir)"
"$(DevEnvDir)../../SDK\v2.0\Bin\gacutil.exe" /u "$(TargetName)"
"%SystemRoot%\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe" "$(TargetPath)"
(在项目里面还对64位和32位系统进行了判断,因为两种系统.net目录是不同的)$(DevEnvDir)是vs路径,$(TargetPath)就是项目的输出文件,第一行把他从gac中删除,接着运行InstallUtil.exe来安装服务,
这里有两个值得注意的问题,就是在运行InstallUtil进行安装的时候,待安装的模块一定不要在Gac里,否则,如果你有引用其他不在GAC中的项目,那安装会报
System.IO.FileNotFoundException:找不到引用的XX程序集或者他的依赖项,这是因为由于你的程序集在GAC中,运行的时候运行环境会在GAC的目录中中找你引用的程序集,如果找不到,就报告错误了,所以我需要先从gac中删除这个项目,另外,路径最后用双引号扩起来,不然如果路径中有空格可能会报错
最后重申一下一些注意事项
1)所有需要放入GAC的项目必须签名,方法如图
2)保证所有需要被企业服务调用到的服务都是ComVisible的
方法是在你的项目的AssemblyInfo.cs里面加上[assembly: ComVisible(true)]
或者找到项目属性Application页,点击AssemblyInfo按钮,把最下面的Make assembly COM-Visible勾选上(见图)
3)最后,最后为需要放入GAC的程序集固定一个版本号,否则每次编译,都会把一个新版本的dll放入GAC,等你打开GAC列表的时候,会看到一长串名字相同但版本不同的dll
(上图对应的地方设置Assembly Version)