精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (11)
|
|
---|---|
作者 | 正文 |
发表时间:2011-02-24
很多人这样设计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等等)是在有窗口站的环境下运行的,那么它们在接收到服务器通知后就可以弹出一个可以看见的窗体了。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-02-24
leogao_emcom 写道 很多人这样设计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等等)是在有窗口站的环境下运行的,那么它们在接收到服务器通知后就可以弹出一个可以看见的窗体了。
记得有一个方法, http://social.technet.microsoft.com/Forums/zh-CN/w7itproui/thread/9cdc0c96-42e1-4e6d-8f29-78077e87e7b2 |
|
返回顶楼 | |
发表时间:2011-02-24
leogao_emcom 写道 很多人这样设计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等等)是在有窗口站的环境下运行的,那么它们在接收到服务器通知后就可以弹出一个可以看见的窗体了。
其实类似杀毒软件都是Windows Service, 明显都是可以直接使用UI的。 |
|
返回顶楼 | |
发表时间:2011-02-24
引用 记得有一个方法, http://social.technet.microsoft.com/Forums/zh-CN/w7itproui/thread/9cdc0c96-42e1-4e6d-8f29-78077e87e7b2 这只是启动了另外一个进程,不在启动另外一个进程的情况下,能不能? |
|
返回顶楼 | |
发表时间:2011-02-24
杀毒软件也是间接的,用类似通信的办法绕过windows service这个限制的,而不是直接。
|
|
返回顶楼 | |
发表时间:2011-02-24
public partial class Service1 : ServiceBase
{ public Service1() { InitializeComponent(); } protected override void OnStart(string[] args) { Form ooo = new Form(); ooo.Show(); } protected override void OnStop() { } } 使用installutil安装一下,并且attach到debugger上,debug一下,窗体果然是不能跳出来显示的,即使是release模式build后,安装,start,也是不行的。我说的就是这样的情况 |
|
返回顶楼 | |
发表时间:2011-02-24
这样的描述并不正确。windowsservice是可以与桌面交互的。但是必须在service安装时添加与桌面交互选项。或者手工在service的属性里修改。然后才有可能进行ui操作。当然楼主分离ui的思路是好的,因为没有ui的服务会降低内存消耗。
|
|
返回顶楼 | |
发表时间:2011-02-25
即使在安装时添加与桌面交互选项,也没有效果,已经试过了。
|
|
返回顶楼 | |
发表时间:2011-02-25
引用 windowsservice是可以与桌面交互的。但是必须在service安装时添加与桌面交互选项 这句话应该修正为,在开发模式下,在为Service添加的ServiceProcessInstaller属性中的Account设置为LocalSystem,然后编译,使用installutil进行安装到windows Service编录(管理器),然后在对应的服务属性中【登录】页中,设置本地系统账户的【允许与桌面交互】选项被选中,最后启动服务,此时桌面就会显示出来。 |
|
返回顶楼 | |
发表时间:2011-02-25
哇哇,窗体是出来了,但是在UI上无法进行操作?我没有找到问题所在。需要再继续探讨一下
|
|
返回顶楼 | |