现在的位置: 首页 > 综合 > 正文

C#编程控制Com+服务

2013年10月04日 ⁄ 综合 ⁄ 共 6544字 ⁄ 字号 评论关闭
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
 
     }
 
 
 

抱歉!评论已关闭.