艾伟:.NET实现可交互的WINDOWS服务

  这几天想做个文件监控服务,看了一下网上的关于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{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);    }}

 

时间: 2024-10-26 15:50:57

艾伟:.NET实现可交互的WINDOWS服务的相关文章

.NET实现可交互的WINDOWS服务

这几天想做个文件监控服务,看了一下网上的关于WINDOWS服务的文章,数量都不少,都只讲了如何做一个最基本的服务,却没有讲述如何与用户进行交互.查看了MSDN,看一下关于服务的描述: Windows 服务应用程序在不同于登录用户的交互区域的窗口区域中运行.窗口区域是包含剪贴板.一组全局原子和一组桌面对象的安全对象.由于 Windows 服务的区域不是交互区域,因此 Windows 服务应用程序中引发的对话框将是不可见的,并且可能导致程序停止响应.同样,错误信息应记录在 Windows 事件日志中

Visual Basic .NET 代码示例:与 Windows 服务交互 (2003年2月17日)

Visual Basic .NET 代码示例:与 Windows 服务交互 (2003年2月17日) 此示例显示了如何通过代码控制已安装的 Windows 服务. http://www.microsoft.com/china/msdn/library/dnvssamp/html/vbcs_InteractingwithaWindowsService.asp

vista和win7在windows服务中交互桌面权限问题解决方法:穿透Session 0 隔离_C#教程

Windows 服务在后台执行着各种各样任务,支持着我们日常的桌面操作.有时候可能需要服务与用户进行信息或界面交互操作,这种方式在XP 时代是没有问题的,但自从Vista 开始你会发现这种方式似乎已不起作用. Session 0 隔离实验 下面来做一个名叫AlertService 的服务,它的作用就是向用户发出一个提示对话框,我们看看这个服务在Windows 7 中会发生什么情况. using System.ServiceProcess; using System.Windows.Forms;

设置Windows服务允许进行桌面交互,实现屏幕监控

默认情况下,Windows服务基于安全考虑,是不允许任何服务程序和桌面进行交互的,也就是说,使用任何的Windows Form 的很多特性将会莫名奇妙的不起作用,如进行屏幕截图,或者使用System.Windows.Form.Timer对象也不行.由于Windows服务具有难以调试的特点,如果不注意这点,你反复检查自己的代码,都很难发现问题的所在的,我开始就是摸索了很久才发现,呵呵. Windows服务的优点有:1. 能够自动运行.2. 不要求用户交互.3. 在后台运行. 一般情况下,Windo

用C#开发Windows服务监控系统使用

window|监控 摘要 本文将向你展示如何用C#开发一个Windows服务来记录系统使用情况. 每一个人都想知道他们每天在什么时间启动和关闭自己的系统,以及系统每天运行了多少时间.如果用一个DataGrid控件来显示系统启动.关闭及所消耗的时间将是一个不错的主意. 在本文中,我提供了一种方法来实现这一目标-使用C#开发一个Windows服务.其实,每个人都了解一点Windows服务.但是,为了介绍之目的,我仅尽可能少得解释一下Windows服务.然后,我们来讨论如何设计一个这样的应用程序. 一

使用srvany.exe将程序安装成windows服务的详细教程

srvany.exe介绍 srvany.exe是Microsoft Windows Resource Kits工具集的一个实用的小工具,用于将任何EXE程序作为Windows服务运行.也就是说srvany只是其注册程序的服务外壳,这个特性对于我们 来说非常实用,我们可以通过它让我们的程序以SYSTEM账户启动,或者实现随机器启动而自启动,也可以隐藏不必要的窗口,比如说控制台窗口等等. 资源下载 你可以通过下载并安装Microsoft Windows Resource Kits 获得或者直接在本文

Windows服务编写(Windows Service,system权限)程序显示界面与用户交互(xp,win7通用)_C#教程

1.VC2008中编写"Windows服务"(Windows Service)程序 源码资源下载:/201604/yuanma/TestService_jb51.rar vc2008下新建一个 ATL 项目-> 选择创建一个"服务"类型的ATL 项目TestService,将生成如下代码, class CTestServiceModule : public CAtlServiceModuleT< CTestServiceModule, IDS_SERVI

C#通过创建Windows服务启动程序的方法详解_C#教程

本文实例讲述了C#通过创建Windows服务启动程序的方法.分享给大家供大家参考,具体如下: 1. 新建一个Windows服务应用程序 创建项目-->Visual C# 左侧的"+"-->Windows -->Windows 服务(右侧模板)-->输入名称,确定创建项目 2. 设置Windows服务的属性(Windows服务里没有窗体,所以点击左侧设计器里空白的地方即可在右侧属性栏里看到属性) 这里属性是控制服务器是否可以停止,暂停,继续等等的操作.根据需要选择

使用PowerShell找到可写的Windows服务并利用

本文讲的是使用PowerShell找到可写的Windows服务并利用,从DidierStevens的博客学到了一些技巧,本文将要对其中涉及到的技巧进行测试总结,并开源一个powershell脚本,用来寻找可被替换的服务,实现自动化利用. 0x01 简介 本文将要介绍以下内容: · 使用c#编写可供Windows服务调用的程序 · psexec的-i参数使用技巧 · sc命令使用技巧 · 通过powershell获取服务对应的可执行文件路径 · 自动化利用脚本开发细节 0x02 使用c#编写可供W