`
wanggp
  • 浏览: 149671 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

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);
           
    }


}

分享到:
评论
1 楼 dxdx1407 2018-01-10  
一顿API操作猛如虎,最后没跑出效果。。。

相关推荐

    C#2008欢迎窗体启动窗体

    在C#中,我们可以通过以下步骤实现欢迎窗体的启动: 1. **创建项目**:在Visual Studio中,选择“文件”&gt;“新建”&gt;“项目”,然后选择"C# Windows 应用程序"模板,创建一个新的Windows Forms应用程序项目。 2. **...

    winfrom Windows服务监控exe进程,启动exe窗体应用程序

    本话题关注的是如何通过C#编程,让一个WinForm应用程序(Windows服务)监控另一个exe进程,并在需要时启动该exe的窗体应用。 首先,让我们深入理解每个组件: 1. **WinForm**: WinForm是.NET Framework提供的一种...

    Window 服务与窗体交互

    4. **安装服务**:使用`InstallUtil.exe`工具或在代码中实现安装逻辑,将服务添加到系统服务列表中。 5. **调试和测试**:在开发过程中,可以使用Visual Studio的调试功能模拟服务环境。部署后,用户可以通过窗体来...

    C#源码-Windows窗体

    通过研究这些源码,你可以学习到如何初始化窗体、添加控件、编写事件处理程序、实现数据绑定等技巧,进一步提升你的C# Windows窗体开发能力。 总之,C# Windows窗体是开发Windows桌面应用程序的常用工具,掌握其...

    C#启动窗体的制作—基于线程技术实现

    在C#编程中,创建一个启动窗体是应用程序与用户交互的第一步,它通常是程序运行时首先显示的界面。本文将深入探讨如何基于线程技术来实现C#启动窗体,以便在主程序加载之前展示一些加载动画或者信息,提供更好的用户...

    C#贪吃蛇游戏 Windows窗体

    【C#贪吃蛇游戏 Windows窗体】是一个适合初学者的编程项目,它利用Microsoft的Visual Studio 2019开发环境,通过Windows窗体应用程序(Windows Forms Application)实现了一个经典的游戏——贪吃蛇。这个项目的核心...

    C# 用户登陆窗体 登陆过程实现方法

    在C#编程中,创建一个用户登录窗体是构建应用程序的基本步骤之一,特别是在Windows Forms(WinForm)应用中。这个过程涉及到验证用户凭据、处理交互逻辑以及管理窗口生命周期。以下将详细介绍如何实现一个标准的C# ...

    C#控制WinForm窗体间数据交互的方法

    ### C#控制WinForm窗体间数据交互的方法 在C#开发中,Windows Forms(WinForms)是一种常用的应用程序框架,用于创建桌面应用程序。在实际项目中,经常会遇到需要在不同窗体之间传递数据的情况。本文将详细介绍几种...

    C#003启动窗体动画显示

    总结来说,"C#003启动窗体动画显示"涉及了如何在C#的Windows Forms或WPF环境中,通过定时器、图形API或者内置的动画机制,为启动窗体添加动态效果,以提升应用程序的视觉吸引力和用户体验。实际应用中,开发者可以...

    C#中用代码在窗体上任意添加控件

    在C#编程环境中,开发Windows桌面应用程序时,我们经常需要在窗体上动态地添加控件,以便根据用户的交互或程序需求自定义界面布局。本文将深入探讨如何在C#中通过代码实现这一功能,特别是在窗体上双击时添加文本框...

    C# Winform 实现窗体间切换

    在C# Winform应用开发中,窗体间的切换是一个常见的需求,这通常涉及到多个窗体之间的交互和数据管理。...在实际项目中,开发者可以根据具体需求,灵活运用上述技术和设计原则来实现更复杂的窗体交互逻辑。

    C#通过子窗体刷新父窗体

    在C#编程中,有时我们需要在子窗体中操作数据并实时更新到主窗口,也就是父窗体。...这一机制不仅适用于VS2008,也是.NET框架下通用的窗体交互方式。理解并掌握这一机制,有助于构建更加高效和灵活的多窗体应用程序。

    C#实现动态等待窗体WaitForm

    在C#编程中,动态等待窗体...通过以上步骤,我们可以成功地在C#中实现一个动态等待窗体,为用户提供友好的交互体验。在实际开发中,还可以根据项目的具体需求对其进行扩展,例如添加自定义动画效果或增加更多反馈信息。

    C#实现从剪贴板复制图像到窗体

    在C#编程中,将剪贴板中的图像复制到窗体是一种常见的操作,尤其是在开发具有图形用户界面(GUI)的应用程序时。这个过程涉及到Windows Forms控件和剪贴板类的使用,使得用户能够通过复制粘贴的方式在应用程序中处理...

    C#与halcon窗体控件交互

    在C#窗体设计界面,可以添加一个`UserControl`控件,然后在代码中将Halcon的HView对象绑定到这个控件上,使其显示Halcon的图像处理结果。 ```csharp using HalconDotNet; // 创建Halcon视图窗口 HView hView = new...

    C# 启动隐藏窗体(只显示托盘)

    在C#编程中,有时我们希望创建一个应用程序,它在启动时不显示主窗口,而是...用户可以通过托盘图标与程序进行交互,包括显示/隐藏窗体以及退出程序。这使得应用程序可以在后台安静地运行,同时保持对用户的可用性。

    C#实现窗体打开动画效果

    总之,C#的Windows Forms提供了丰富的功能来实现各种窗体动画,通过合理利用控件和事件,开发者可以创造出独特的用户体验。在设计动画时,应考虑动画的流畅性、速度和视觉效果,以确保它们既美观又不影响程序的运行...

    C#windows窗体程序---记事本

    标题 "C# Windows窗体程序---记事本" 指的是使用C#编程语言开发的一个基于Windows操作系统的图形用户界面(GUI)应用程序,模仿了经典的记事本工具。这个程序通常会包含基本的文本编辑功能,如打开、保存、复制、...

    C#Windows窗体模拟折半查找程序

    在C#编程环境中,开发Windows窗体应用程序是一种常见的实践,它允许用户通过图形用户界面(GUI)与软件进行交互。在这个特定的项目中,我们关注的是实现一个模拟折半查找算法的Windows窗体应用。折半查找,也称为二...

    C#实现Windows服务

    在本文中,我们将深入探讨如何使用C#语言创建Windows服务,以及如何管理和调试这些服务。Windows服务是一种特殊类型的应用程序,它们在后台无用户界面的情况下持续运行,适用于服务器环境。服务能够自动启动,无需...

Global site tag (gtag.js) - Google Analytics