日期:2014-05-17  浏览次数:21221 次

Windows Service开发的一个经典问题

很多人这样设计Windows Service,希望在某种条件下,比如某个事件发生后,希望Windows Service弹出一个窗体!

其实这非常不正确,不管是C#,VB.net还是C++创建的Windows Service是被OS windows子系统调用的和维护的,

恰恰它没有桌面站,OS在启动Windows子系统的时候,会默认创建两类东西,就是有窗口站的桌面(其实也是一个窗口以及窗口树结构),另外一个就是无窗口站的环境,Windows Service恰恰运行在这个环境中,其含义是没有客户操作区的表面,那么即使你在Windows Service的OnStart方法中new一个Window对象并调用其Show方法,你也看不到有窗体弹出!

?

但是你可以使用一个办法绕过这个限制,那就是使用Windows Service作为服务器端,做一个WCF/Remoting服务,

让一个独立进程(最好系统一起启动的)作为客户端,使用双向回调实现的观察者模式(可以使用委托实现,或者WCF就支持回调的方式,不过需要绑定也支持两个通道,并且回调的行为必须是OneWay的),服务在某个条件下通知被注册的客户端,此时客户端程序就可以有所动作,因为一个exe程序(Console等等)是在有窗口站的环境下运行的,那么它们在接收到服务器通知后就可以弹出一个可以看见的窗体了。

?

?

?

1 楼 ycaicainiao 2011-02-24  
<div class="quote_title">leogao_emcom 写道</div><div class="quote_div"><p>很多人这样设计Windows Service,希望在某种条件下,比如某个事件发生后,希望Windows Service弹出一个窗体!</p>
<p>其实这非常不正确,不管是C#,VB.net还是C++创建的Windows Service是被OS windows子系统调用的和维护的,</p>
<p>恰恰它没有桌面站,OS在启动Windows子系统的时候,会默认创建两类东西,就是有窗口站的桌面(其实也是一个窗口以及窗口树结构),另外一个就是无窗口站的环境,Windows Service恰恰运行在这个环境中,其含义是没有客户操作区的表面,那么即使你在Windows Service的OnStart方法中new一个Window对象并调用其Show方法,你也看不到有窗体弹出!</p>
<p>?</p>
<p>但是你可以使用一个办法绕过这个限制,那就是使用Windows Service作为服务器端,做一个WCF/Remoting服务,</p>
<p>让一个独立进程(最好系统一起启动的)作为客户端,使用双向回调实现的观察者模式(可以使用委托实现,或者WCF就支持回调的方式,不过需要绑定也支持两个通道,并且回调的行为必须是OneWay的),服务在某个条件下通知被注册的客户端,此时客户端程序就可以有所动作,因为一个exe程序(Console等等)是在有窗口站的环境下运行的,那么它们在接收到服务器通知后就可以弹出一个可以看见的窗体了。</p>
<p>?</p>
<p>?</p>
<p>?</p></div><br/>记得有一个方法,

http://social.technet.microsoft.com/Forums/zh-CN/w7itproui/thread/9cdc0c96-42e1-4e6d-8f29-78077e87e7b2
2 楼 ycaicainiao 2011-02-24  
<div class="quote_title">leogao_emcom 写道</div><div class="quote_div"><p>很多人这样设计Windows Service,希望在某种条件下,比如某个事件发生后,希望Windows Service弹出一个窗体!</p>
<p>其实这非常不正确,不管是C#,VB.net还是C++创建的Windows Service是被OS windows子系统调用的和维护的,</p>
<p>恰恰它没有桌面站,OS在启动Windows子系统的时候,会默认创建两类东西,就是有窗口站的桌面(其实也是一个窗口以及窗口树结构),另外一个就是无窗口站的环境,Windows Service恰恰运行在这个环境中,其含义是没有客户操作区的表面,那么即使你在Windows Service的OnStart方法中new一个Window对象并调用其Show方法,你也看不到有窗体弹出!</p>
<p>?</p>
<p>但是你可以使用一个办法绕过这个限制,那就是使用Windows Service作为服务器端,做一个WCF/Remoting服务,</p>
<p>让一个独立进程(最好系统一起启动的)作为客户端,使用双向回调实现的观察者模式(可以使用委托实现,或者WCF就支持回调的方式,不过需要绑定也支持两个通道,并且回调的行为必须是OneWay的),服务在某个条件下通知被注册的客户端,此时客户端程序就可以有所动作,因为一个exe程序(Console等等)是在有窗口站的环境下运行的,那么它们在接收到服务器通知后就可以弹出一个可以看见的窗体了。</p>
<p>?</p>
<p>?</p>
<p>?</p></div><br/>其实类似杀毒软件都是Windows Service,
明显都是可以直接使用UI的。
3 楼 leogao_emcom 2011-02-24  
引用

记得有一个方法, http://social.technet.microsoft.com/Forums/zh-CN/w7itproui/thread/9cdc0c96-42e1-4e6d-8f29-78077e87e7b2


这只是启动了另外一个进程,不在启动另外一个进程的情况下,能不能?
4 楼 leogao_emcom 2011-02-24  
杀毒软件也是间接的,用类似通信的办法绕过windows service这个限制的,而不是直接。
5 楼 leogao_emcom 2011-02-24  
public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
        }