Winapi c# Проблема с отловом хуков в отдельных приложениях х64

Добров времени суток! Я пишу на c# и сейчас заинтересован в хуках. Отлавливая нажатия через WH_KEYBOARD_LL моя программа игнорирует события в некоторых приложениях. Причем в других приложениях, вне зависимости от их архитектуры 32 и 64 - хуки проходят. Проблемы в таких приложениях как диспетчер задач, spy++ (version 17.0.34511.75) - это 64битные приложения, сдуя по тому же диспетчеру задач (архитектуру запущенных приложений можно посмотреть во вкладке "подробности", графа "платформа"). хотя в spy++(version 7.10) хуки приходят.

Что не так? Куда копать?

использовал Vanara.PInvoke;

код прилагаю:

----------------------------Form1---------------------------------


using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using Vanara.PInvoke;
using static RawInput.Form1;
using static Vanara.PInvoke.Kernel32;
using static Vanara.PInvoke.User32;



namespace RawInput
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        ActWinTrace actWinTrace = new ActWinTrace();
        MsgWinTrace msgWinTrace = new MsgWinTrace();
        KbWinTrace2 kbWinTrace2 = new KbWinTrace2();

        private void Form1_Load(object sender, EventArgs e)
        {
            actWinTrace.ActiveWindowChanged += ActWinTrace_ActiveWindowChanged;

            PrintLabelTextTheActWindow();
            kbWinTrace2.OnKeyPressed += KbWinTrace2_OnKeyPressed;
            kbWinTrace2.OnWindowChanged += KbWinTrace2_OnWindowChanged;
        }

        private void KbWinTrace2_OnWindowChanged(object? sender, KbWinTrace2.WindowChanged e)
        {
            labelHWNDActiveWindow.Text = e._hwndNewWindow.ToString();
            labelHWNDOldWindow.Text = e._hwndOldWindow.ToString();
        }

        private void KbWinTrace2_OnKeyPressed(object? sender, KbWinTrace2.KeyPressedArgs e)
        {
            textBox1.Text = $"{e.KeyPressed}";
        }

        private void ActWinTrace_ActiveWindowChanged(object? sender, ActiveWindowChangedEventArgs e)
        {
            PrintLabelTextTheActWindow();
        }

        /// <summary>
        /// выводит в лейбл имя активного окна
        /// </summary>
        void PrintLabelTextTheActWindow()
        {
            labelActiveWindow.Text = "Active Window:\r\n" + actWinTrace.GetActiveWindowTitle();
            labelOldWindow.Text = "Foreground Window:\r\n" + GetForegroundWindow().ToString();
        }

        private void button1_Click(object sender, EventArgs e)
        {

        }



       
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            kbWinTrace2.UnHookAll();
        }
    }
}




winapi вывел в отдельный класс

---------------------------------class---------------------------------------------------


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Vanara.PInvoke.User32;
using Vanara.PInvoke;
using static Vanara.PInvoke.Kernel32;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Input;

namespace RawInput
{
    public class KbWinTrace2
    {

        public HHOOK hKeyboardbHook; //api идентификатор hookа 
        public HHOOK msgHOOK; //api идентификатор hookа
        public HHOOK ShellProcHook; //api идентификатор hookа

        public HookProc lpfn;// api, отсюда сюда летят хуки



        HWND hLauncherWnd = IntPtr.Zero; //hwnd моего приложения
        uint hMsg = new ();// хукнутое сообщение
        MSG gMSG = new MSG ();//// хукнутое сообщение2

        private const int WM_KEYDOWN = 0x0100;
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYUP = 0x0101;
        private const int WM_SYSKEYDOWN = 0x0104;
       
        
        
        public KbWinTrace2() 
        {
            //экземпляр делегата, ссылки на функцию winapi HookProc
            lpfn = Callback;

            //устанавливает хук на события клавы
            hKeyboardbHook = SetWindowsHookEx(HookType.WH_KEYBOARD_LL, lpfn);
            //устанавливает хук на сообщения
            msgHOOK = SetWindowsHookEx(HookType.WH_GETMESSAGE, lpfn);
            //устанавливает хук на оболочку
            ShellProcHook = SetWindowsHookEx(HookType.WH_SHELL, lpfn);



            //регистрация уникального сообщения в нашем приложении (в майне и  в длл обявлять надо бы)
            hMsg = RegisterWindowMessage("HookSampleMessage");

          
        }



        /// <summary>
        /// Функция обратного вызова, Система вызывает эту функцию каждый раз, когда новое событие ввода с клавиатуры будет помещено в очередь ввода потока, используемую с функцией SetWindowsHookExA/SetWindowsHookExW .       
        /// <param name="nCode">Код, который используется в процедуре перехватчика для определения способа обработки сообщения.
        ///Если значение nCode меньше нуля, процедура перехватчика должна передать сообщение функции CallNextHookEx без дальнейшей обработки и возвращать значение, возвращаемое CallNextHookEx.
        ///Этот параметр может принимать одно из указанных ниже значений.Параметры wParam и lParam содержат сведения о сообщении клавиатуры.</param>
        /// <param name="wParam">Этот параметр может иметь одно из следующих сообщений: WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN или WM_SYSKEYUP.</param>
        /// <param name="lParam"></param>
        /// <returns>
        /// Если процедура перехватчика обработала сообщение, она может вернуть ненулевое значение (nCode), чтобы система не могла передать сообщение остальной части цепочки перехватчиков или процедуре целевого окна
        /// </returns>
        private nint Callback(int nCode, nint wParam, nint lParam)
        {
            //клавиатура
            //если сообщение - это код клавиатуры/мыши с параметром нажатия 
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
            {
                //магия
                int vkCode = Marshal.ReadInt32(lParam);

                //уведомитель о событии нажатия клавиши, передает подписчикам код кдавиши
                OnKeyPressed?.Invoke(this, new KeyPressedArgs((Keys)vkCode));   
            }
            
            
            //оболочка Заменяется окно верхнего уровня. Окно существует, когда система вызывает этот перехватчик.
            if (nCode == 13)
            {
                OnWindowChanged?.Invoke(this, new WindowChanged(wParam, lParam));
                return 0;
            }
                
            //сообщения 13
            if (nCode >= 0 && hLauncherWnd!= IntPtr.Zero) 
            {
                PostMessage(hLauncherWnd, hMsg, wParam, lParam);
            }



            return CallNextHookEx(hKeyboardbHook, nCode, wParam, lParam);
        }


        #region  MyEvents

        /// <summary>
        /// мой тип агрумента, необходим моего события нажатия, для передачи  параметра (клавишии Keys) в событии
        /// </summary>
        public class KeyPressedArgs : EventArgs 
        {
            //параметр хранящий нажатую клавишу для экзкмпляра класса события "нажатие клавиши"
            public Keys KeyPressed { get; private set; }
            
            
            /// <summary>
            /// конструктор по умолчанию
            /// экземпляр класса должен быть обязательно с клавишей
            /// </summary>
            /// <param name="key">нажатая клавиша</param>
            public KeyPressedArgs(Keys key) 
            {// экземпляр класса должен быть обязательно с клавишей
                KeyPressed = key;
            }


        }
        /// <summary>
        /// мое событие нажатия на клавишу с моим параметром Keys (нажатой клавиши)
        /// </summary>
        public event EventHandler<KeyPressedArgs> OnKeyPressed;




        /// <summary>
        ///  мой тип агрумента, необходим моего события изменения окна верхнего уровня, для передачи  хендлов окон в событии
        /// </summary>
        public class WindowChanged : EventArgs
        {
            public HWND _hwndOldWindow{ get; private set; }
            public HWND _hwndNewWindow{ get; private set; }

            public WindowChanged(HWND oldWindow, HWND newWindow)
            {
                _hwndOldWindow = oldWindow;
                _hwndNewWindow = newWindow;
            }

        }
        public event EventHandler<WindowChanged> OnWindowChanged;
        #endregion

        // реализовано в конструкторе
        // хук захватывается в конструкторе

        public bool SetKeyboardHook(HWND hParentWnd)///https://www.youtube.com/watch?v=evkO-5UO-q4 10.11.20 timecode
        {
            hLauncherWnd = hParentWnd;
            if(hKeyboardbHook.IsNull)
            hKeyboardbHook = SetWindowsHookEx(HookType.WH_KEYBOARD_LL, lpfn);
            return hKeyboardbHook.IsNull ? false : true; 
        }
        //private HHOOK SetHook()
        //{
        //    return SetWindowsHookEx(HookType.WH_KEYBOARD_LL, lpfn);
        //}

        public void UnHookAll() 
        {
            if(!hKeyboardbHook.IsNull)
            UnhookWindowsHookEx(hKeyboardbHook);
            if(!msgHOOK.IsNull)
            UnhookWindowsHookEx(msgHOOK);
        }
       
       // nint Callback 
       
    }
}
```C#```

Ответы (1 шт):

Автор решения: aepot

Вы не можете отслеживать поведение или состояние привелегированных приложений не обладая правами.

Поэтому чтобы отследивать системные приложения, такие как Диспетчер Задач, нужно самому выполнить элевацию, то есть запуститься от имени администратора.

Права админа можно требовать принудительно, прописав это требование в манифест приложения.

→ Ссылка