由于個人需要,想找一個鍵盤記錄的程序,從網上下載了很多,多數都是需要注冊的,另外也多被殺軟查殺。于是決定自己寫一個,如果作為一個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);
???????????
??? }
}