由于个人需要,想找一个键盘记录的程序,从网上下载了很多,多数都是需要注册的,另外也多被杀软查杀。于是决定自己写一个,如果作为一个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);
}
}
分享到:
相关推荐
Window 服务与窗体交互 Window Service 与Form 交互
本文将为大家介绍的是WinForm窗体之间的数据交互等问题,包括自定义一个构造函数等等问题。
C#与halcon窗体控件交互,可以使用。可以供给大家看看,也是从别处得到的。 C#与halcon窗体控件交互,可以使用。可以供给大家看看,也是从别处得到的
C#两种等待窗体的实现 做C#开发过程中,数据交互难免要等待,为了避免假死状态,特找到这两种等待窗体的实现
C#,使用,BackgroundWorker ,实现,后台操作窗体 C#,使用,BackgroundWorker ,实现,后台操作窗体 C#,使用,BackgroundWorker ,实现,后台操作窗体 C#,使用,BackgroundWorker ,实现,后台操作窗体 C#,使用...
C# 两个窗体之间实时传递数据的实例。利用委托和事件的方法,从子窗体传送数据到主窗体。比较安全。
C#实现的等待窗体,采用多线程技术。效果不错,用动画进行播放。
主要介绍了C#实现winform用子窗体刷新父窗体及子窗体改变父窗体控件值的方法,涉及C#窗体交互的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
两个DataGridView通过委托实时传值,安全高效 C# 两个窗体之间实时传递数据的实例。利用委托和事件的方法,从子窗体传送数据到主窗体。比较安全。
C#多线程编程实例 线程与窗体交互源码.rar
winform利用窗体属性实现窗体之间传值,实现窗体之间的交互!
C#winform 窗体与Webbrowser控件的相互交互
在.net中轻松掌握Windows窗体间的数据交互,查询中常用到,可以方便的实现筛选.
使用 Microsoft® .NET Framework 可以轻松地创建基于 Windows® 的应用程序:您只需创建窗体、添加控件,然后将窗体连接到业务逻辑,这样就可以了。但这样的应用程序并不能为用户提供真正需要的交互功能。例如,当...
C# MDI父窗体中同时显示两个子窗体,子窗体按钮控制另一个子窗体,弹出窗口 GDI绘图,并重绘
C#多线程编程实例 线程与窗体交互源码,该示例演示如何在线程安全的模式下调用Windows窗体上的控件。
C#窗体值传 多窗体传值 C#实例 C#交互 本人QQ:280067279,加时注明:CSDN,我也想多认识些编程的朋友.
一个简单的窗体交互绘图程序,实现添加设置绘图参数的菜单项和对话框。在设置对话框中,设置笔的种类、风格、粗细和颜色;设置刷的种类、填充样式、填充颜色、填充图片等 -Form a simple interactive drawing ...