1

ウィンドウアプリケーション c# .net を開発しています。そのアプリケーションは、他のマシン(ウィンドウマシン)をリモートデスクトップ接続で接続し、そのリモートマシンでユーザーが行ったことを監視するために使用されます。

ユーザーの操作を監視するために、リモート マシンへの接続時に SetWindowsHookEx() メソッドを使用して、WH_KEYBOARD_LL および WH_MOUSE_LL フックのカスタム フック プロシージャをグローバル フック プロシージャとしてインストールしました。

ユーザーがリモート マシンからログオフするとき、UnhookWindowsHookEx() を使用してフック プロシージャを解放する必要があります。ここで、「フック ハンドルが無効です」(無効なフック ハンドルを意味します) というメッセージが表示されると、問題が発生します。

このエラーは常に発生するわけではありません。それは時々起こりました。

私は c# .net 開発の初心者です。このエラーについてはわかりません。

したがって、 UnhookWindowsHookEx() が呼び出されたときにそのエラーが発生する理由を知りたいです。

誰か助けてください。

私のコードは次のとおりです。

try
{
  HookManager.KeyDown -= HookManager_KeyDown;
  HookManager.KeyUp -= HookManager_KeyUp;
  HookManager.MouseUp -= HookManager_MouseUp;
}
catch (Exception ex)
{
  // error is written to log file if uninstalling hook procedure is failed
  LogController.Instance.Fatal(ex.Source + CommonConstants.TAB + ex.Message);
}

.....

上記のコードは、次のコードを実行します。

public static partial class HookManager
{
  private static int s_KeyboardHookHandle;

  private static event KeyEventHandler s_KeyDown;

  public static event KeyEventHandler KeyDown
  {
       add
       {
           EnsureSubscribedToGlobalKeyboardEvents();
           s_KeyDown += value;
       }
       remove
       {
           s_KeyDown -= value;
           TryUnsubscribeFromGlobalKeyboardEvents();
       }
   }

   private static void EnsureSubscribedToGlobalKeyboardEvents()
    {
        // install Keyboard hook only if it is not installed and must be installed
        if (s_KeyboardHookHandle == 0)
        {
            //See comment of this field. To avoid GC to clean it up.
            s_KeyboardDelegate = KeyboardHookProc;
            //install hook
            s_KeyboardHookHandle = SetWindowsHookEx(
                WH_KEYBOARD_LL,
                s_KeyboardDelegate,
                Marshal.GetHINSTANCE(
                    Assembly.GetExecutingAssembly().GetModules()[0]),
                0);
            //If SetWindowsHookEx fails.
            if (s_KeyboardHookHandle == 0)
            {
                //Returns the error code returned by the last unmanaged function called using platform invoke that has the DllImportAttribute.SetLastError flag set. 
                int errorCode = Marshal.GetLastWin32Error();
                //do cleanup

                //Initializes and throws a new instance of the Win32Exception class with the specified error. 
                throw new Win32Exception(errorCode);
            }
        }
    }

   private static void TryUnsubscribeFromGlobalKeyboardEvents()
    {
        //if no subsribers are registered unsubsribe from hook
        if (s_KeyDown == null &&
            s_KeyUp == null &&
            s_KeyPress == null)
        {
            ForceUnsunscribeFromGlobalKeyboardEvents();
        }
    }

   private static void ForceUnsunscribeFromGlobalKeyboardEvents()
    {
        if (s_KeyboardHookHandle != 0)
        {
            //uninstall hook
            int result = UnhookWindowsHookEx(s_KeyboardHookHandle);
            //reset invalid handle
            s_KeyboardHookHandle = 0;
            //Free up for GC
            s_KeyboardDelegate = null;
            //if failed and exception must be thrown
            if (result == 0)
            {
                //Returns the error code returned by the last unmanaged function called using platform invoke that has the DllImportAttribute.SetLastError flag set. 
                int errorCode = Marshal.GetLastWin32Error();
                //Initializes and throws a new instance of the Win32Exception class with the specified error. 
                throw new Win32Exception(errorCode);
            }
        }
    }

 private static int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
    {
        //indicates if any of underlaing events set e.Handled flag
        bool handled = false;

        if (nCode >= 0)
        {
            //read structure KeyboardHookStruct at lParam
            KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
            //raise KeyDown
            if (s_KeyDown != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
            {
                Keys keyData = (Keys)MyKeyboardHookStruct.VirtualKeyCode;
                KeyEventArgs e = new KeyEventArgs(keyData);
                s_KeyDown.Invoke(null, e);
                handled = e.Handled;
            }

            // raise KeyPress
            if (s_KeyPress != null && wParam == WM_KEYDOWN)
            {
                bool isDownShift = ((GetKeyState(VK_SHIFT) & 0x80) == 0x80 ? true : false);
                bool isDownCapslock = (GetKeyState(VK_CAPITAL) != 0 ? true : false);

                byte[] keyState = new byte[256];
                GetKeyboardState(keyState);
                byte[] inBuffer = new byte[2];
                if (ToAscii(MyKeyboardHookStruct.VirtualKeyCode,
                          MyKeyboardHookStruct.ScanCode,
                          keyState,
                          inBuffer,
                          MyKeyboardHookStruct.Flags) == 1)
                {
                    char key = (char)inBuffer[0];
                    if ((isDownCapslock ^ isDownShift) && Char.IsLetter(key)) key = Char.ToUpper(key);
                    KeyPressEventArgs e = new KeyPressEventArgs(key);
                    s_KeyPress.Invoke(null, e);
                    handled = handled || e.Handled;
                }
            }

            // raise KeyUp
            if (s_KeyUp != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP))
            {
                Keys keyData = (Keys)MyKeyboardHookStruct.VirtualKeyCode;
                KeyEventArgs e = new KeyEventArgs(keyData);
                s_KeyUp.Invoke(null, e);
                handled = handled || e.Handled;
            }

        }

        //if event handled in application do not handoff to other listeners
        if (handled)
            return -1;

        //forward to other application
        return CallNextHookEx(s_KeyboardHookHandle, nCode, wParam, lParam);
    }
4

0 に答える 0