.NET实现可交互的WINDOWS服务(转载自CSDN"烈火蜓蜻")

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

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

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

  那么来看一下如果才能实现一个可交互的服务呢。步骤与实现基本的服务一样(各位可自行参考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
{
    public class Service1 : System.ServiceProcess.ServiceBase
    {
        /// 
        /// 必需的设计器变量。
        /// 
        private System.ComponentModel.Container components = null;
        Thread threadForm = null;
        public Service1()
        {
            // 该调用是 Windows.Forms 组件设计器所必需的。
            InitializeComponent();

            // TODO: 在 InitComponent 调用后添加任何初始化
        }

        #region 组件设计器生成的代码
        /// 
        /// 设计器支持所需的方法 - 不要使用代码编辑器 
        /// 修改此方法的内容。
        /// 
        private void InitializeComponent()
        {
            // 
            // Service1
            // 
            this.ServiceName = "JadeWatchService";

        }
        #endregion
        [STAThread]
        static void Main()
        {
            System.ServiceProcess.ServiceBase.Run( new Service1() );

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

        /// 
        /// 设置具体的操作,以便服务可以执行它的工作。
        /// 
        protected override void OnStart( string[] args )
        {
            threadForm = new Thread( new ThreadStart( FormShow ) );
            threadForm.Start();
        }

        /// 
        /// 停止此服务。
        /// 
        protected override void 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" )]
        static extern int GetDesktopWindow();

        [DllImport( "user32.dll" )]
        static extern IntPtr GetProcessWindowStation();

        [DllImport( "kernel32.dll" )]
        static extern IntPtr GetCurrentThreadId();

        [DllImport( "user32.dll" )]
        static extern IntPtr GetThreadDesktop( IntPtr dwThread );

        [DllImport( "user32.dll" )]
        static extern IntPtr OpenWindowStation( string a, bool b, int c );

        [DllImport( "user32.dll" )]
        static extern IntPtr OpenDesktop( string lpszDesktop, uint dwFlags,
        bool fInherit, uint dwDesiredAccess );

        [DllImport( "user32.dll" )]
        static extern IntPtr CloseDesktop( IntPtr p );

        [DllImport( "rpcrt4.dll", SetLastError = true )]
        static extern IntPtr RpcImpersonateClient( int i );


        [DllImport( "rpcrt4.dll", SetLastError = true )]
        static extern IntPtr RpcRevertToSelf();

        [DllImport( "user32.dll" )]
        static extern IntPtr SetThreadDesktop( IntPtr a );

        [DllImport( "user32.dll" )]
        static extern IntPtr SetProcessWindowStation( IntPtr a );
        [DllImport( "user32.dll" )]
        static extern IntPtr CloseWindowStation( IntPtr a );
    }
}
原文地址:https://www.cnblogs.com/baofengyu/p/8484937.html