• .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 );
        }
    }
  • 相关阅读:
    实验 1:Mininet 源码安装和可视化拓扑工具
    ORACLE 数据库异常关闭处理办法
    Tomcat安装及配置教程
    关于Eclipse无server选项的解决方法
    2020软件工程作业02
    2020软件工程作业01
    C语言II作业01
    C语言总体概览
    C语言寒假大作战04
    C语言寒假大作战03
  • 原文地址:https://www.cnblogs.com/baofengyu/p/8484937.html
Copyright © 2020-2023  润新知