zoukankan      html  css  js  c++  java
  • C# 通过服务启动窗体(把窗体添加到服务里)实现用户交互的windows服务[转发]

    由于个人需要,想找一个键盘记录的程序,从网上下载了很多,多数都是需要注册的,另外也多被杀软查杀。于是决定自己写一个,如果作为一个windows应用程序,可以实现抓取键盘的记录。想要实现随系统启动的话,其中一种方法就是要作为windows服务,把代码直接写到服务里边并不能抓取到键盘的记录,从网上翻阅资料及查看msdn才知道:

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

    服务程序一般使用的是LocalSystem帐户,拥有自己的window station,和Default桌面,这个window station是不能于用户交互的,也就是说,你不能在上面显示窗口,它也不接受用户的鼠标、键盘等输入。

    我们使用用户帐户登录以后,看到的桌面,是WinSta0(window station)下的Default(desktop).
    WinSta0下有3个桌面:
    WinLogon :以Logon对话框的形式出现.当用户登录以后,WinLogon.exe切换到Default desktop.
    Default :这是Explorer.exe和所有用户程序窗口出现的地方,也就是我们通常使用windows看见的地方.应用程序就运行在这个桌面上
    Screen saver :系统空闲的时候,运行屏保的桌面.

    当你在“计算机管理”中选择一个服务,修改属性,选择“登录”标签页的“允许服务与桌面交互”,那么该服务就使用的是WinSta0(window station)下的Default(desktop). 你也就可以与你的服务进行交互操作了。这时,你能获取default的桌面位图,因为线程的桌面就是WinSta0下的Default。要想同时获得Winlogon桌面位图,应该先把线程的桌面设置成Winlogon。

    此部分代码公布如下:

    //Service1.Designer.cs文件

    using System.Threading;

    namespace KeyBoard
    {
        partial class Service1
        {
            /// <summary>
            /// 必需的设计器变量。
            /// </summary>
            private System.ComponentModel.IContainer components = null;
            Thread threadForm = null;

            /// <summary>
            /// 清理所有正在使用的资源。
            /// </summary>
            /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }

            #region 组件设计器生成的代码

            /// <summary>
            /// 设计器支持所需的方法 - 不要
            /// 使用代码编辑器修改此方法的内容。
            /// </summary>
            private void InitializeComponent()
            {
                //
                // Service1
                //
                this.ServiceName = "Service1";

            }

            #endregion

        }
    }

    //Service1.cs文件

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.ServiceProcess;
    using System.Text;
    using System.Threading;
    using System.Runtime.InteropServices;

    namespace KeyBoard
    {
        public partial class Service1 : ServiceBase
        {
            public Service1()
            {
                InitializeComponent();
            }

            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;

                MouseKeyBoard f=new MouseKeyBoard(); //此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);
               
        }


    }

  • 相关阅读:
    POJ3258River Hopscotch(二分)
    POJ3273Monthly Expense(二分)
    POJ1002487-3279(map)
    HDU 3123 GCC
    POJ2031Building a Space Station
    POJ3096Surprising Strings(map)
    模板类
    POJ1265Area
    【ZZ】C 语言中的指针和内存泄漏 & 编写高效的C程序与C代码优化
    学习笔记之MySQL
  • 原文地址:https://www.cnblogs.com/vic_lu/p/1957842.html
Copyright © 2011-2022 走看看