2011-10-20 4 views
1

두 가지 코드가 있는데, 글로벌 후크를 등록한다는 점에서 매우 유사합니다.글로벌 키보드 후크가 작동하지만 글로벌 쉘 후크가 실패합니다.

public class KeyboardHook : IDisposable 
{ 
    #region Events 
    private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); 
    public delegate void HookEventHandler(object sender, KeyboardHookEventArgs e); 
    public event HookEventHandler KeyDown; 
    public event HookEventHandler KeyUp; 
    #endregion 

    #region Constants 
    private const int WH_KEYBOARD_LL = 13; 
    private const int WM_KEYDOWN = 0x0100; 
    private const int WM_SYSKEYDOWN = 0x0104; 
    private LowLevelKeyboardProc _proc = null; 
    private static IntPtr _hookID = IntPtr.Zero; 
    #endregion 

    #region Imports 
    [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); 

    #endregion 

    #region Constructor 
    public KeyboardHook() 
    { 
     _proc = new LowLevelKeyboardProc(HookCallback); 
     _hookID = SetHook(_proc); 
    } 

    #endregion 


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

    private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) 
    { 
     //if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) 
     if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)) 
     { 
      int vkCode = Marshal.ReadInt32(lParam); 
      WinForms.Keys key = (WinForms.Keys)vkCode; 
      if (this.KeyDown != null) 
       this.KeyDown(this, new KeyboardHookEventArgs(vkCode)); 
     } 
     return CallNextHookEx(_hookID, nCode, wParam, lParam); 
    } 

    #endregion 

    #region Destructor 
    public void Dispose() 
    { 
     UnhookWindowsHookEx(_hookID); 
    } 
    #endregion 
} 

글로벌 쉘 후크 등록 :

등록 글로벌 키보드 후크 어떤 이유로, 키보드 후크 작품

public enum ShellEvents 
    { 
     HSHELL_WINDOWCREATED = 1, 
     HSHELL_WINDOWDESTROYED = 2, 
     HSHELL_ACTIVATESHELLWINDOW = 3, 
     HSHELL_WINDOWACTIVATED = 4, 
     HSHELL_GETMINRECT = 5, 
     HSHELL_REDRAW = 6, 
     HSHELL_TASKMAN = 7, 
     HSHELL_LANGUAGE = 8, 
     HSHELL_ACCESSIBILITYSTATE = 11 
    } 

    public class ShellHook 
    { 
     #region Events 
     private delegate IntPtr ShellProc(int nCode, IntPtr wParam, IntPtr lParam); 
     public delegate void HookEventHandler(object sender, ShellHookEventArgs e); 
     public event HookEventHandler WindowActivated; 
     #endregion 

     #region Constants 
     private const int WH_SHELL = 10; 
     private ShellProc _proc = null; 
     private static IntPtr _hookID = IntPtr.Zero; 
     #endregion 

     #region Imports 
     [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     private static extern IntPtr SetWindowsHookEx(int idHook, 
      ShellProc 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); 

     [DllImport("user32.dll")] 
     static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); 
     #endregion 

     #region Fields 
     #endregion 

     #region Constructor 
     public ShellHook() 
     { 
      _proc = new ShellProc(HookCallback); 
      _hookID = SetHook(_proc); 
     } 
     #endregion 

     #region Methods 
     private IntPtr SetHook(ShellProc proc) 
     { 
      using (Process curProcess = Process.GetCurrentProcess()) 
      using (ProcessModule curModule = curProcess.MainModule) 
      { 
       return SetWindowsHookEx(WH_SHELL, proc, 
        GetModuleHandle(curModule.ModuleName), 0); 
      } 
     } 

     private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) 
     { 
      if (nCode >= 0 && wParam.Equals(ShellEvents.HSHELL_WINDOWACTIVATED)) 
      { 
       string windowTitle = GetWindowTitle(wParam); 
       if (this.WindowActivated != null) 
        this.WindowActivated(this, new ShellHookEventArgs(windowTitle)); 
      } 
      return CallNextHookEx(_hookID, nCode, wParam, lParam); 
     } 

     private string GetWindowTitle(IntPtr hWnd) 
     { 
      const int nChars = 256; 
      StringBuilder Buff = new StringBuilder(nChars); 

      if (GetWindowText(hWnd, Buff, nChars) > 0) 
      { 
       return Buff.ToString(); 
      } 
      return null; 
     } 
     #endregion 

     #region Destructor 
     public void Dispose() 
     { 
      UnhookWindowsHookEx(_hookID); 
     } 
     #endregion 
    } 

을하지만, 쉘 후크 실패 (SetWindowsHookEx 반환 0 콜백에 도달하지 못함).

왜 그런가?

답변

2

나는 내 자신의 질문에 답할 것입니다. pinvoke.net에서이 인용 당신은 낮은 수준의 후크를 제외하고 마이크로 소프트 .NET 프레임 워크 글로벌 후크를 구현할 수 없습니다, 그러나 ... 왜

을 설명합니다. 전역 후크를 설치하려면 유효하고 일관된 함수 호출이 필요한 다른 프로세스에 자체를 삽입하려면 후크에 네이티브 동적 연결 라이브러리 (DLL) 내보내기가 있어야합니다. 이 은 .NET Framework에서 지원하지 않는 DLL 내보내기가 필요합니다. 관리되는 코드는 에 대해 일관된 값의 개념을 가지고 있지 않으므로이 함수 포인터는 에 내장 된 프록시이기 때문입니다.

관련 문제