我自己做了一个进程外com的简单例子:comserver.exe和comclient.exe,然后用两种方法测试:
1.不启动comserver,直接运行comclient的话,在进程管理器里能够看到comserver正在运行,当退出comclient时,comserver也相应的退出了,这些都是正常的。2.先启动comserver,然后运行comclient的话,进程管理器中仍只有一个comserver进程,这也应该是对的,可是在我退出comclient的时候,发现comserver进程也退出了,按照我自己对com生存期的理解,comserver此时不应该退出的吧?因为它自己的引用计数不是0啊,不知道我理解的对否?各位高手指正,谢谢

解决方案 »

  1.   

    ComServer是使用单一实例类厂吗?如果不是,你看到的可能是新启动的comserver实例。
      

  2.   

    to jeffchen:
    什么叫“单一实例”类厂?能给解释一下吗?我的comserver只实现了一个接口。
    你的意思是我的第二个测试中,启动comclient后,先前的comserver已经被杀掉了?而我看到的是comclient新创建的comserver?但是com的机制是如果被请求的comserver.exe已经启动的话就不会再启动它了,就直接创建类厂对象了啊。
    那如果我想在comclient退出后不结束comserver进程,应该怎么实现呢?多谢
      

  3.   

    “单一实例”指多次要求启动一个应用程序以提供服务时,只启动一个实例,后续的请求都会被处理,但返回的实例句柄是同一个。这个效果一般使用互斥量来实现,如果用ATL编写,可以简单的指定一个宏即可。楼主的原因是因为没有锁住服务器,当COM客户退出时,它将类厂的引用记数减一,由于为零,因此服务器退出。楼主如果用MFC写的服务器,应该在InitInstance中根据不是以请求启动时(即通过判断命令行参数是否带有/Embber(可能记错),一般向导会自动添加),就调用LockServer(这个名字是乱起的,旨在说明功能,实际实现相同功能的函数随不同的类库不同)以锁定服务器(即增加类厂的引用记数),再在ExitInstance中解锁服务器。对于ATL编写的在具有同样功能的函数中锁定和解锁服务器即可。
      

  4.   

    哦,我是用atl编写的comserver,但是找不到在哪个函数中添加锁计数器啊,只见到有一个自动生成的UnLock()函数,大侠,帮到底吧,多谢,我可以再添分的,呵呵
      

  5.   

    在楼主的CAtlModule派生类中重载PreMessageLoop,在其中先调用父类的PreMessageLoop,再通过GetCommandLine得到命令行,然后解析命令行(如果是MFC,CWinApp::PraseCommandLine可以帮助你解析,虽然ATL也提供了,但不能解析/Embedding或/Automation,因此楼主必须自己手动解析),看是否包含/Embedding或/Automation命令行参数,包含了说明exe是由COM运行时期库启动的,没有包含说明是普通的启动,就调用父类的Lock();以锁住exe。再在派生类中重载PostMessageLoop,如上判断(可以通过一个成员变量的记录以避免代码重复)是否应该锁住exe,如果是(即不带有/Embedding或/Automation),调用Unlock();以解锁exe。如果楼主嫌自己解析命令行参数太麻烦,可以使用MFC提供的帮助类CCommandLineInfo(具体用法请参考MSDN),不过必须为你的ATL工程添加MFC支持。