cyt
首先,要控制windows services,是比较容易的事情,一堆现成的例子。
SYNtService 就是一个很好的例子。
要控制一个窗口退出是十分容易的事情,PostMessage就可以解决问题。
要控制console退出,也有很多现成的方法。比较通用的方法:
1、TerminateProcess
   最原始、最暴力的强制console退出的方法。console进程毫无还手之力就over了。但我希望console在推出之前至少能处理一下“后事”。

2、signal / raise
   原来windows也有signal,不过kill换成了raise。但是相对Unix系列的signal功能就差很远了。而且有一个麻烦的地方就是raise只能对本console生效,而不能对指定的process。
   可以在signal里面指定一个call back函数,在收到SIGINT/SIGTERM之类的时候,处理一下事情,然后通知各个线程结束。
   既然不能raise其他进程,是否这个功能就不能用了呢?其实可以考虑一下CreateRemoteThread,然后在别人的进程里面raise……

3、SetConsoleCtrlHandler / GenerateConsoleCtrlEvent
    这个是console专门用来处理Ctrl-C/Ctrl-Break/以及windows关机事件等的处理方法。比signal更强大。而且说明中写了,可以对其他的进程进行处理(还可以对进程组处理)。用网上的话说就是:很女子,很弓虽!
    但是要注意,如果要对其创建的子进程进行处理的时候,创建子进程必须要使用CREATE_NEW_PROCESS_GROUP标志。另外一点,文档写的比较隐晦的就是,进程必须要有console窗口。否则,调用GenerateConsoleCtrlEvent会返回6,说ERROR_INVALID_HANDLE。
    问题来了,Service本身是没有console窗口的,Service建立的子进程就必须要自带窗口了。但是一般为了美观,Service启动的进程都不想带有窗口。那就变成了子进程没有console窗口,GenerateConsoleCtrlEvent失效了。
    在网上查了很多资料(怎么没看到很黄很暴力呢???),其中在 Louis K. Thomas <louiNØSP@Msth@hotmÑOSP@Mail.coNÕSP@Mm> 的 SendSignal 提到一种做法,就是先获得kernel32!CtrlRoutine的入口,然后通过CreateRemoteThread的方法,让远程的console来执行kernel32!CtrlRoutine。但这种方法有个问题,在获得kernel32!CtrlRoutine的时候,也是使用GenerateConsoleCtrlEvent来获得。但是Service自己本身没有console窗口,一调用GenerateConsoleCtrlEvent也是出错。
而另一篇 google讨论组 文章,里面提到原来可以先AllocConsole、然后GenerateConsoleCtrlEvent、然后FreeConsole……于是解决方案就变成:
Service里面:
  先AllocConsole
  然后利用GenerateConsoleCtrlEvent获得kernel32!CtrlRoutine
  然后FreeConsole
  当需要结束进程的时候,就调用CreateRemoteThread,把kernel32!CtrlRoutine的代码注入到子process中执行
  这样大家都看不到console窗口(service里面AllocConsole很快,看不到窗口出来,甚至怀疑根本就有没有窗口出来),同时又能通知子进程优雅地退出。

存在问题:如果我的机器作为服务器启动,即没有进入登录状态,不知道这样启动的Service会不会有问题呢??暂时还没有时间测试。


   
   

posted on 2008-01-08 16:07 cyt 阅读(4363) 评论(4)  编辑 收藏 引用 所属分类: Work
Comments
  • # re: 如何在windows service里面控制console程序退出
    eXile
    Posted @ 2008-01-09 11:45
    没大明白,有代码就好了。。。  回复  更多评论   
  • # re: 如何在windows service里面控制console程序退出
    梦醒惊魂
    Posted @ 2008-03-18 02:36
    呵呵,不错,很黄很爆力,正找这个问题,难怪我都不成功,原来GenerateConsoleCtrlEvent必须要有console窗口。真是太感谢了,交个朋友好嘛?

    QQ:522986976  回复  更多评论   
  • # re: 如何在windows service里面控制console程序退出
    cyt
    Posted @ 2008-05-05 17:55
    乐意交这个朋友

    后来我测试过,CreateRemoteThread这种方法其实也是可以。这种方法按作者的说法有一个问题是:如果新的进程带有窗口,就会失败。但是在我的情况下不会有窗口。所以我最后选择这种方法了。连dos窗口闪一下都没有了,完美解决。  回复  更多评论   
  • # re: 如何在windows service里面控制console程序退出
    DDGG
    Posted @ 2008-06-10 16:19
    cyt能给个用CreateRemoteThread实现的例子么?谢谢啊!  回复  更多评论   

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理