0

我在过去两天遇到一个问题,我想获取他单击的用户进程。就像用户单击记事本一样,我的程序应该告诉我用户单击了记事本。打开记事本。如果用户点击计算器,我的程序也会告诉用户点击了计算器。计算器进程正在运行。

为此,我使用了此代码。钩子管理器,它给我鼠标点击事件,但不给我过程。

我只收到鼠标 intptr 事件。

private static void WindowEventCallback(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
     Console.WriteLine("Event {0}", hwnd);// it is giving me mouse event 
     /*uint pid;
     GetWindowThreadProcessId(hwnd, out pid);// it gives me process id
     Process p = Process.GetProcessById((int)pid);// now here exception occured not in vs studio but when i run its exe then its gives me access violation exception
     if (!my.ContainsKey(p.MainWindowTitle.ToString()))
     {
          my.Add(p.MainWindowTitle.ToString(), p.Id.ToString());
          Console.WriteLine("\r\n");
          Console.WriteLine("Status = Running");
          Console.WriteLine("\r\n Window Title:" + p.MainWindowTitle.ToString());
          Console.WriteLine("\r\n Process Name:" + p.ProcessName.ToString());
          Console.WriteLine("\r\n Process Starting Time:" + p.StartTime.ToString());
     }*/
}

完整的代码是

    static void Main(string[] args)
    {
        HookManager.SubscribeToWindowEvents();

        EventLoop.Run();
    }


    public static class HookManager
    {
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint ProcessId);
        public static void SubscribeToWindowEvents()
        {
            if (windowEventHook == IntPtr.Zero)
            {
                windowEventHook = SetWinEventHook(
                    EVENT_SYSTEM_FOREGROUND, // eventMin
                    EVENT_SYSTEM_FOREGROUND, // eventMax
                    IntPtr.Zero,             // hmodWinEventProc
                    WindowEventCallback,     // lpfnWinEventProc
                    0,                       // idProcess
                    0,                       // idThread
                    WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);

                if (windowEventHook == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
        }

        static Dictionary<string, string> my = new Dictionary<string, string>();


        private static void WindowEventCallback(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
        {
            Console.WriteLine("Event {0}", hwnd);
            /*uint pid;
            GetWindowThreadProcessId(hwnd, out pid);
            Process p = Process.GetProcessById((int)pid);
            if (!my.ContainsKey(p.MainWindowTitle.ToString()))
            {
                my.Add(p.MainWindowTitle.ToString(), p.Id.ToString());
                Console.WriteLine("\r\n");
                Console.WriteLine("Status = Running");
                Console.WriteLine("\r\n Window Title:" + p.MainWindowTitle.ToString());
                Console.WriteLine("\r\n Process Name:" + p.ProcessName.ToString());
                Console.WriteLine("\r\n Process Starting Time:" + p.StartTime.ToString());


            }*/
        }
    }

    private static IntPtr windowEventHook;

    private delegate void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SetWinEventHook(int eventMin, int eventMax, IntPtr hmodWinEventProc, WinEventProc lpfnWinEventProc, int idProcess, int idThread, int dwflags);
    [DllImport("user32.dll", SetLastError = true)]
    private static extern int UnhookWinEvent(IntPtr hWinEventHook);

    private const int WINEVENT_INCONTEXT = 4;
    private const int WINEVENT_OUTOFCONTEXT = 0;
    private const int WINEVENT_SKIPOWNPROCESS = 2;
    private const int WINEVENT_SKIPOWNTHREAD = 1;

    private const int EVENT_SYSTEM_FOREGROUND = 3;


    public static class EventLoop
    {
        public static void Run()
        {
            MSG msg;

            while (true)
            {

                if (PeekMessage(out msg, IntPtr.Zero, 0, 0, PM_REMOVE))
                {
                    if (msg.Message == WM_QUIT)
                        break;

                    TranslateMessage(ref msg);
                    DispatchMessage(ref msg);
                }
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct MSG
        {
            public IntPtr Hwnd;
            public uint Message;
            public IntPtr WParam;
            public IntPtr LParam;
            public uint Time;
        }

        const uint PM_NOREMOVE = 0;
        const uint PM_REMOVE = 1;

        const uint WM_QUIT = 0x0012;

        [DllImport("user32.dll")]
        private static extern bool PeekMessage(out MSG lpMsg, IntPtr hwnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg);
        [DllImport("user32.dll")]
        private static extern bool TranslateMessage(ref MSG lpMsg);
        [DllImport("user32.dll")]
        private static extern IntPtr DispatchMessage(ref MSG lpMsg);
    }
}
4

1 回答 1

0

如果你想把你的逻辑放在鼠标点击处理程序中,你可以简单地调用GetActiveWindow来获取窗口句柄(如果你还没有的话)。然后您可以使用GetWindowThreadProcessId从窗口句柄中获取进程 ID。

然而,每次点击鼠标都这样做看起来有点过头了。您可能应该考虑挂钩到活动窗口更改。检查此以获取详细信息:活动窗口上的 Windows 系统事件是否已更改?

于 2013-06-21T06:18:41.003 回答