C#,需要帮助分开一个初学者程序

时间:2016-02-17 18:57:58

标签: c#

作为初学者课程,我想将此教程http://null-byte.wonderhowto.com/how-to/create-simple-hidden-console-keylogger-c-sharp-0132757/移植到Windows窗体应用程序。 这应该向用户显示在名为'lblMessage'的标签内按下了什么键。

我现在将代码分成两部分。

Form1.cs的

using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.IO;

namespace WindowsFormsApplication3
{
    public partial class Form1 : Form
    {
        public GlobalKeyHook hook = new GlobalKeyHook();

        public Form1()
        {
            InitializeComponent();

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // Origin
            // _hookID = SetHook(_proc);

            hook._hookID = hook.SetHook(_proc);

        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            // Origin
            // UnhookWindowsHookEx(_hookID);

            hook.UnhookWindowsEx(_hookID);

        }
    }
}

GlobalKeyHook.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;

namespace WindowsFormsApplication3
{
    class GlobalKeyHook : Form
    {
        #region DLLs
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook,
            LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
            IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);
        #endregion


        #region Fields and delegation
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private static LowLevelKeyboardProc _proc = HookCallback;
        public static IntPtr _hookID = IntPtr.Zero;

        public delegate IntPtr LowLevelKeyboardProc(
        int nCode, IntPtr wParam, IntPtr lParam);
        #endregion

        public GlobalKeyHook()
        {
            IntPtr hookID = _hookID;
            LowLevelKeyboardProc proc = _proc;
        }

        static Form form = new Form();

        #region Methods
        private static IntPtr HookCallback(
            int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                Console.WriteLine((Keys)vkCode);
                form.Text = vkCode.ToString();
            }
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

        public static IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
                GetModuleHandle(curModule.ModuleName), 0);
            }
        }
        #endregion
    }
}

但我无法在Form1类中使用public static IntPtr _hookID,方法SetHook()或DLL UnhookWindowsHookEx。是不是可以从另一个类使用这个“类型”?

2 个答案:

答案 0 :(得分:2)

您需要将GlobalKeyHook类设置为public class GlobalKeyHook

答案 1 :(得分:2)

不确定这会解决您的所有问题,但可以帮助您避免其中一些问题。

如果这是.net 4.0或更高版本,则SetWindowsHookEX()调用可能会返回0(失败),因为.net不再模拟托管dll的本机模块。要解决此问题,您可以为LoadLibrary()添加DllImport,如下所示:

[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
    public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);

然后在致电SetWindowsHookEX()之前的某个地方执行此操作:

IntPtr hinstDLL = UnsafeMethods.LoadLibrary("user32.dll"); 

并按照以下方式致电SetWindowsHookEX()

SetWindowsHookEx(WH_KEYBOARD_LL, proc,
            hinstDLL, 0);

基本上SetWindowsHookEX()需要一个有效的模块句柄,它会验证但从不实际使用它。加载user32的原因是,因为你正在从中调用函数,所以你可以使用它。

此外,在您的构造函数中,只需将其设置为IntPtr.Zero。如果您始终将其设置为IntPtr.Zero,则无需进行_hookID。同样值得注意的是,如果运行此计算机的计算机使用IntPtr,则不到win7sp1.Zero将无效(至少99%肯定。)

我强烈建议你查看This set of hooks他们有一个很好的钩子库实现,你可以随意扩展它。