在VSTO加载项中获取Word处理的键盘输入

nin*_*ite 5 c# vsto office-addins

我正在尝试使用MouseKeyboardActivityMonitor Nugget收听Word AddIn中的键盘输入。当我注册KeyboardHookListener时,我可以接收除Word以外的每个程序上的每个键盘输入。

这可能是某些Word内部保护的原因,还是我缺少了什么?

我有Windows 7 64位和Word 2016 32位。

k_keyListener = new KeyboardHookListener(new GlobalHooker());
k_keyListener.Enabled = true;
k_keyListener.KeyDown += new System.Windows.Forms.KeyEventHandler(hook_OnKeyDown);

public void hook_OnKeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
    log.Info("Pressed key: " + e.KeyCode.ToString());
}
Run Code Online (Sandbox Code Playgroud)

Jer*_*son 5

我不使用Global Hooker,并且我的代码有效。我在Word中对其进行了明确的测试(并且知道它可以在Excel,PowerPoint,Access等环境中工作)。

对于它的价值,微软永远担心Office应用程序被黑客入侵,而您的安全软件可能实际上就是原因。它毕竟是KeyLogger,容易被标记为病毒注入攻击。

public partial class ThisAddIn
{
    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        //enable keyboard intercepts
        KeyboardHooking.SetHook();
    }

    private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
    {
        //disable keyboard intercepts
        KeyboardHooking.ReleaseHook();
    }
}
Run Code Online (Sandbox Code Playgroud)

添加此键盘类:

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

namespace WordAddInKeyHandler
{
    class KeyboardHooking
    {
        [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)]
        private 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);

        public delegate int LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
        private static LowLevelKeyboardProc _proc = HookCallback;
        private static IntPtr _hookID = IntPtr.Zero;

        //declare the mouse hook constant.
        //For other hook types, you can obtain these values from Winuser.h in the Microsoft SDK.

        private const int WH_KEYBOARD = 2; // mouse
        private const int HC_ACTION = 0;

        private const int WH_KEYBOARD_LL = 13; // keyboard
        private const int WM_KEYDOWN = 0x0100;

        public static void SetHook()
        {
            // Ignore this compiler warning, as SetWindowsHookEx doesn't work with ManagedThreadId
#pragma warning disable 618
            _hookID = SetWindowsHookEx(WH_KEYBOARD, _proc, IntPtr.Zero, (uint)AppDomain.GetCurrentThreadId());
#pragma warning restore 618

        }

        public static void ReleaseHook()
        {
            UnhookWindowsHookEx(_hookID);
        }

        //Note that the custom code goes in this method the rest of the class stays the same.
        //It will trap if BOTH keys are pressed down.
        private static int HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode < 0)
            {
                return (int)CallNextHookEx(_hookID, nCode, wParam, lParam);
            }
            else
            {
                if (nCode == HC_ACTION)
                {
                    Keys keyData = (Keys)wParam;

                    // CTRL + SHIFT + 7
                    if ((BindingFunctions.IsKeyDown(Keys.ControlKey) == true)
                        && (BindingFunctions.IsKeyDown(Keys.ShiftKey) == true)
                        && (BindingFunctions.IsKeyDown(keyData) == true) && (keyData == Keys.D7))
                    {
                        // DO SOMETHING HERE
                    }

                    // CTRL + 7
                    if ((BindingFunctions.IsKeyDown(Keys.ControlKey) == true)
                        && (BindingFunctions.IsKeyDown(keyData) == true) && (keyData == Keys.D7))
                    {
                        // DO SOMETHING HERE
                    }
                }
                return (int)CallNextHookEx(_hookID, nCode, wParam, lParam);
            }
        }
    }

    public class BindingFunctions
    {
        [DllImport("user32.dll")]
        static extern short GetKeyState(int nVirtKey);

        public static bool IsKeyDown(Keys keys)
        {
            return (GetKeyState((int)keys) & 0x8000) == 0x8000;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果有时间,您可以通过比较Global Hooker源代码和我的代码来检查Global Hooker为何不起作用(特别是与Word一起使用)。

在这里引用我的答案:https : //stackoverflow.com/a/10257266/495455也请参阅XNA作者Govert的答案。