首页 > 解决方案 > 检测到 CallbackOnCollectedDelegate(在 WinEventProc 调用 Process.GetProcessByID 之后)

问题描述

我需要你的指导大师。波纹管按照我的代码。我在事件 3 或 8 发生时捕获窗口的标题,并在事件 9 发生时创建一个计数器。

我的代码运行良好,但是,当我尝试使用函数 GetProcessName 获取 Windows exe 所有者的名称时,我收到错误“检测到 CallbackOnCollectedDelegate”。我已经做了并尝试了我所知道的一切,但没有解决该错误。在开始使用应用程序一段时间后发生错误。

当我不调用我的函数 GetProcessName 时,不会发生错误。

    delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
    [DllImport("user32.dll")]
    static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);

    [DllImport("user32.dll")]
    public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint ProcessId);

    [DllImport("user32.dll")]
    static extern IntPtr GetForegroundWindow();

    private const uint EVENT_SYSTEM_FOREGROUND = 3;
    private const uint EVENT_SYSTEM_CAPTUREEND = 9;
    private const uint EVENT_SYSTEM_CAPTURESTART = 8;
    int counter = 0;

    public Form1()
    {
        InitializeComponent();

        IntPtr handle = IntPtr.Zero;
        SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_CAPTUREEND, IntPtr.Zero, new WinEventDelegate(WinEventProc), 0, 0, 0);
    }

    public void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
    {
        try
        {

            if (eventType == EVENT_SYSTEM_FOREGROUND || eventType == EVENT_SYSTEM_CAPTURESTART && idObject == 0)
            {

                aux1 = GetActiveWindowTitle(hwnd);//A function tha get a name of the title of the window
                if (aux1 != aux2 && string.IsNullOrEmpty(aux1) == false)
                {
                    GetWindowThreadProcessId(hwnd, out pid);
                    pnomelast = GetProcessName((int)pid);//This is the function!!

                    aux2 = aux1;
                    aux1 = "";
                }
            }
            else if (eventType == EVENT_SYSTEM_CAPTUREEND)
            {
                counter = counter + 1;
            }
        }
        catch (Exception e)
        {
        };
    }

    public static string GetProcessName(int processId)
    {
        try
        {
            return Process.GetProcessById(processId).MainModule.FileName.ToString().Split('\\').Last();

        }
        catch (Exception)
        {
            return "";
        }
    }

非常感谢。

标签: c#user32

解决方案


您的问题是 SetWinEventHook 正在动态创建一个没有参考的新委托。由于它是孤立的,它将在下一次垃圾回收时被销毁。

首先新建一个 WinEventDelegate

private static winEventDelegate = new WinEventDelegate(WinEventProc);

然后改变:

SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_CAPTUREEND, IntPtr.Zero, new WinEventDelegate(WinEventProc), 0, 0, 0);

至:

SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_CAPTUREEND, IntPtr.Zero, winEventDelegate, 0, 0, 0);

推荐阅读