C
#编程控制
Com+
服务
创建日期:2006-6-23
适用于:.NET Framework,C#
作者:Dogvane
因为在设计本地升级程序的时候,需要升级一个Com+服务的DLL,因此需要复制DLL之前需要停止Com+的服务,在阅了MSDN帮助后,找到一个Com+ 1.0 Admin Type Library的Com对象,所有的Com+操作都可以通过这个Com对象进行。
实现方法:
1.导出Com对象
2.创建一个用户控制com应用程序的对象
COMAdmin
.COMAdminCatalogClass com = new COMAdmin.COMAdminCatalogClass();
COMAdmin
.COMAdminCatalogCollection list = (COMAdmin.COMAdminCatalogCollection)com.GetCollection("Applications");
这里通过GetCollectoin来取得com应用程序的列表。
这个时候list的列表长度为1,里面并没有任何东西。当初以为是关键字写错了,试了N种其它方法都没有让列表里有值,该死的MSDN对于这个方法偏偏没有任何示例代码可用。最后在查阅网络上N种控制Com+的代码后终于知道,得到的列表需要调用Populate方法才能获得应用程序^_^!
3.禁用Com+应用程序
list.Populate(); //
取得应用程序
System.Collections.IEnumerator i = list.GetEnumerator();
while(i.MoveNext())
{
COMAdmin.ICatalogObject app = (COMAdmin.ICatalogObject)i.Current;
if (app.get_Value("Name").ToString() == _Name)
{
///
禁用 com+ 服务
app.set_Value("IsEnabled", false);
list.SaveChanges(); //
保存本次操作,Com+服务不会停止
}
}
取得所有的Com+应用程序后就是一个遍历的过程,从里面取得自己希望停止的Com+程序(用get_Value(“Name”)方法)。然后将IsEnable产生设置为false,如果是要启用Com+
4.虽然禁用了Com+应用程序,但是DLL有些时候还是不能服务,系统提示DLL文件还是被占用,原因查明后是向前Com+应用程序一直在使用,服务虽然被禁用,但是DLL程序还在运行。最后通过ShutdownApplication方式结束应用程序(相当于把进程杀掉)
com
.ShutdownApplication(_Name);
5.如果只是打算更新某个应用程序里的一个组件(
Components),则不一定要禁用整个程序,只需要禁用该组件就可以了。禁用的方法和禁用Com+应用程序的方法一样,所不同的是,我们在取得组件列表的时候,需要调用
GetCollectionByQuery2这个方法,毕竟所有的组件都是存在于Com+应用程序下面的。
object
key = app.Key; //
指定的Com+ 应用程序
COMAdmin.COMAdminCatalogCollection Components = (COMAdmin.COMAdminCatalogCollection)com.GetCollectionByQuery2("Components", ref key);
Components.Populate(); //
和Com+列表一样,新创建的列表里是没有任何东西的
6.其它的操作方法都类似,通过GetCollectionByQuery的方法取得Com+服务里的各种对象,然后通过这些对象的get_Value和set_Value进行各种Com+属性的设置,修改完成后再通过SaveChages()更新设置即可
注意:
因为xp以后的操作系统,com+使用的接口是
GetCollectionByQuery2,而在win2k下面使用的接口是GetCollectionByQuery。虽然在代码里面可以将针对接口的操作改为GetCollectionByQuery,但是,XP下编译的程序无法在win2K下运行,原因编译时导出的DLL会GetCollectionByQuery2的接口也倒出来,在系统win2K系统下创建对象接口时,找不到该函数,所以会出错。
正确的做法是,工程在发布时,需要到win2K系统下编译。
win9x,win nt 系统没有测试过不清除是否存在这样的问题。
附录:Com+ Service控制类代码
///<summary>
/// Com+ Service
的控制类
///</summary>
internal class ComPlusService : IServiceControl
{
private int _TimeOut = 10;
public int TimeOut
{
get
{
return _TimeOut;
}
set
{
if (value > 0)
_TimeOut = value;
else
_TimeOut = 10;
}
}
string _Name = string.Empty;
COMAdmin.COMAdminCatalogClass com = new COMAdmin.COMAdminCatalogClass();
public ComPlusService(string name)
{
Name = name;
}
#region
IServiceControl Members
public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
}
}
public void Stop()
{
try
{
LcftLog.Logging.Info("Stop Com+ Service: " + _Name);
COMAdmin.COMAdminCatalogCollection list = (COMAdmin.COMAdminCatalogCollection)com.GetCollection("Applications");
list.Populate();
System.Collections.IEnumerator i = list.GetEnumerator();
///
停止 com+ 服务程序(从内存中卸载)
com.ShutdownApplication(_Name);
while(i.MoveNext())
{
COMAdmin.ICatalogObject app = (COMAdmin.ICatalogObject)i.Current;
if (app.get_Value("Name").ToString() == _Name)
{
///
禁用 com+ 服务
app.set_Value("IsEnabled", false);
list.SaveChanges();
///
下面的操作主要是取得 com+ 服务里的组件信息(DLL文件路径)
///
然后判断这些组件是否已经停止(DLL从Com+应用程序里卸载,不存在写保护)
object key = app.Key;
COMAdmin.COMAdminCatalogCollection Components = (COMAdmin.COMAdminCatalogCollection)com.GetCollectionByQuery2("Components", ref key);
Components.Populate();
System.Collections.IEnumerator i2 = Components.GetEnumerator();
while (i2.MoveNext())
{
COMAdmin.ICatalogObject obj2 = (COMAdmin.ICatalogObject)i2.Current;
string dll = obj2.get_Value("DLL").ToString();
int wait = TimeOut;
LcftLog.Logging.Debug(dll);
while(!CanWriteFile(dll))
{
if (wait -- < 0)
break;
System.Threading.Thread.Sleep(500);
}
}
}
}
}
catch (Exception ex)
{
LcftLog.Logging.Error("{0} Stop fail".Replace("{0}", _Name));
throw ex;
}
}
private bool CanWriteFile(string fileName)
{
System.IO.FileStream stream = null;
bool error = false;
try
{
stream = System.IO.File.Open(fileName, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite);
}
catch
{
error = true;
}
if (stream != null)
stream.Close();
return !error;
}
public void Start()
{
try
{
LcftLog.Logging.Info("Start Com+ Service: " + _Name);
COMAdmin.COMAdminCatalogCollection list = (COMAdmin.COMAdminCatalogCollection)com.GetCollection("Applications");
list.Populate();
System.Collections.IEnumerator i = list.GetEnumerator();
while(i.MoveNext())
{
COMAdmin.ICatalogObject app = (COMAdmin.ICatalogObject)i.Current;
if (app.get_Value("Name").ToString() == _Name)
{
app.set_Value("IsEnabled", true);
list.SaveChanges();
}
}
com.StartApplication(_Name);
}
catch (Exception ex)
{
LcftLog.Logging.Error("{0} Start fail".Replace("{0}", _Name));
throw ex;
}
}
#endregion
}