c# - 检测到 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 "";
}
}
非常感谢。
解决方案
您的问题是 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);