欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.NET实现可交互的WINDOWS服务的实例代码

程序员文章站 2024-03-03 17:14:34
  这几天想做个文件监控服务,看了一下网上的关于windows服务的文章,数量都不少,都只讲了如何做一个最基本的服务,却没有讲述如何与用户进行交互。查看了msdn,看一下关...

  这几天想做个文件监控服务,看了一下网上的关于windows服务的文章,数量都不少,都只讲了如何做一个最基本的服务,却没有讲述如何与用户进行交互。查看了msdn,看一下关于服务的描述:

   windows 服务应用程序在不同于登录用户的交互区域的窗口区域中运行。窗口区域是包含剪贴板、一组全局原子和一组桌面对象的安全对象。由于 windows 服务的区域不是交互区域,因此 windows 服务应用程序中引发的对话框将是不可见的,并且可能导致程序停止响应。同样,错误信息应记录在 windows 事件日志中,而不是在用户界面中引发。

   .net framework 支持的 windows 服务类不支持与交互区域(即登录用户)进行交互。同时,.net framework 不包含表示区域和桌面的类。如果 windows 服务必须与其他区域进行交互,则需要访问非托管的 windows api。

  也就是说我们要实现可交互的服务(比如我们想给服务在运行时做一些参数设置等),那我们一定要using system.runtime.interopservices

  那么来看一下如果才能实现一个可交互的服务呢。步骤与实现基本的服务一样(各位可自行参考msdn或网上google一下).

  在实现onstart时要注意,这里可不能弹出一个form什么的。这样做是没有任何反应的。我们可以在这个方法里运行一个线程。该线程需要访问窗口区域对象或桌面对象,当然 framework里是没有提供这些的,要访问非托管代码的。

  来看一下代码,再运行试一下。

复制代码 代码如下:

using system;
using system.collections;
using system.componentmodel;
using system.data;
using system.diagnostics;
using system.serviceprocess;
using system.threading;
using system.runtime.interopservices;
namespace filewatchservice
{
    publicclass service1 : system.serviceprocess.servicebase
    {
        ///
        /// 必需的设计器变量。
        ///
private system.componentmodel.container components =null;
        thread threadform =null;
        public service1()
        {
            // 该调用是 windows.forms 组件设计器所必需的。
            initializecomponent();

            // todo: 在 initcomponent 调用后添加任何初始化
        }

        #region 组件设计器生成的代码
        ///
        /// 设计器支持所需的方法 - 不要使用代码编辑器
        /// 修改此方法的内容。
        ///
privatevoid initializecomponent()
        {
            //
            // service1
            //
this.servicename ="jadewatchservice";

        }
        #endregion
        [stathread]
        staticvoid main()
        {
            system.serviceprocess.servicebase.run(new service1());

        }
        ///
        /// 清理所有正在使用的资源。
        ///
protectedoverridevoid dispose(bool disposing)
        {
            if (disposing)
            {
                if (components !=null)
                {
                    components.dispose();
                }
            }
            base.dispose(disposing);
        }

        ///
        /// 设置具体的操作,以便服务可以执行它的工作。
        ///
protectedoverridevoid onstart(string[] args)
        {
            threadform =new thread(new threadstart(formshow));
            threadform.start();
        }

        ///
        /// 停止此服务。
        ///
protectedoverridevoid onstop()
        {
            if (threadform !=null)
            {
                if (threadform.isalive)
                {
                    threadform.abort();
                    threadform =null;
                }
            }
        }

        void formshow()
        {

            getdesktopwindow();
            intptr hwinstasave = getprocesswindowstation();
            intptr dwthreadid = getcurrentthreadid();
            intptr hdesksave = getthreaddesktop(dwthreadid);
            intptr hwinstauser = openwindowstation("winsta0", false, 33554432);
            if (hwinstauser == intptr.zero)
            {
                rpcreverttoself();
                return;
            }
            setprocesswindowstation(hwinstauser);
            intptr hdeskuser = opendesktop("default", 0, false, 33554432);
            rpcreverttoself();
            if (hdeskuser == intptr.zero)
            {
                setprocesswindowstation(hwinstasave);
                closewindowstation(hwinstauser);
                return;
            }
            setthreaddesktop(hdeskuser);

            intptr dwguithreadid = dwthreadid;

            form1 f =new form1(); //此form1可以带notifyicon,可以显示在托盘里,用户可点击托盘图标进行设置
            system.windows.forms.application.run(f);


            dwguithreadid = intptr.zero;
            setthreaddesktop(hdesksave);
            setprocesswindowstation(hwinstasave);
            closedesktop(hdeskuser);
            closewindowstation(hwinstauser);
        }

        [dllimport("user32.dll")]
        staticexternint getdesktopwindow();

        [dllimport("user32.dll")]
        staticextern intptr getprocesswindowstation();

        [dllimport("kernel32.dll")]
        staticextern intptr getcurrentthreadid();

        [dllimport("user32.dll")]
        staticextern intptr getthreaddesktop(intptr dwthread);

        [dllimport("user32.dll")]
        staticextern intptr openwindowstation(string a, bool b, int c);

        [dllimport("user32.dll")]
        staticextern intptr opendesktop(string lpszdesktop, uint dwflags,
        bool finherit, uint dwdesiredaccess);

        [dllimport("user32.dll")]
        staticextern intptr closedesktop(intptr p);

        [dllimport("rpcrt4.dll", setlasterror =true)]
        staticextern intptr rpcimpersonateclient(int i);


        [dllimport("rpcrt4.dll", setlasterror =true)]
        staticextern intptr rpcreverttoself();

        [dllimport("user32.dll")]
        staticextern intptr setthreaddesktop(intptr a);

        [dllimport("user32.dll")]
        staticextern intptr setprocesswindowstation(intptr a);
        [dllimport("user32.dll")]
        staticextern intptr closewindowstation(intptr a);
    }
}