力SetWinEventHook是从主线程调用 [英] Force SetWinEventHook to be called from main thread

查看:374
本文介绍了力SetWinEventHook是从主线程调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想注册新创建的进程的一些对象级的WinEvents挂钩,但作为官方的文档说:




有关外OF-背景事件,该事件被调用SetWinEventHook在同一个线程上提供。




我的问题是,我从不是主要原因之一,这将导致在没有收到任何回调以外的线程调用SetWinEventHook主线程。我一直在寻找一种方式来触发(从另一个线程)在主线程SetWinEventHook方法调用。明知这是一个控制台应用程序,调用而BeginInvoke解决方案没有奏效。我也试过事件和事件处理程序。



我希望我的问题不会被误解。下面的代码和输出。

  //存储回调作为一个字段,以确保垃圾收集不动它
//而在托管代码被使用,这是比使用的GCHandle
静态WinEventDelegate procDelegate =新Native.WinEventDelegate(WinEventProc)更容易;

静态无效WinEventProc(IntPtr的hWinEventHook,UINT事件类型,IntPtr的HWND,
INT idObject,诠释idChild,UINT dwEventThread,UINT dwmsEventTime)
{
Console.WriteLine( 回调,TID =+ Thread.CurrentThread.ManagedThreadId);
}

ManagementEventWatcher processStartEvent =新ManagementEventWatcher(SELECT * FROM Win32_ProcessStartTrace);

无效processStartEvent_EventArrived(对象发件人,EventArrivedEventArgs E)
{
串processName = e.NewEvent.Properties [ProcessName] Value.ToString()。
INT进程ID = Convert.ToInt32(e.NewEvent.Properties [的ProcessID]值。);
工艺过程= Process.GetProcessById(进程ID);
IntPtr的钩= SetWinEventHook(事件ID,事件ID,IntPtr.Zero,procDelegate,(UINT)process.Id,
GetWindowThreadProcessId(process.MainWindowHandle,IntPtr.Zero),
Native.WINEVENT_OUTOFCONTEXT |母语.WINEVENT_SKIPOWNPROCESS | Native.WINEVENT_SKIPOWNTHREAD);
如果(钩== IntPtr.Zero)Console.WriteLine(挂钩失败);
Console.WriteLine(事件,TID =+ Thread.CurrentThread.ManagedThreadId);
}

无效watchProcess()
{
processStartEvent.EventArrived + =新EventArrivedEventHandler(processStartEvent_EventArrived);
processStartEvent.Start();
}

静态无效的主要(字串[] args)
{
Console.WriteLine(主,TID =+ Thread.CurrentThread.ManagedThreadId);
watchProcess();
MessageBox.Show(消息循环);
}



输出:



<块引用>

为主,TID = 1结果
事件,TID = 4 //重复多次,新工艺创造



解决方案

曾经有过同样的问题。从任何形式使用Invoke方法:

  this.Invoke(新MethodInvoker(()=> StartEventListener())); 



问候


I'm trying to register some object-level WinEvents hooks on new created processes but as the official documentation says :

For out-of-context events, the event is delivered on the same thread that called SetWinEventHook.

My problem is that I'm calling SetWinEventHook from a thread other than the main one which will result in not receiving any callback in the main thread. I have been looking for a way to trigger (from another thread) SetWinEventHook method call in the main thread. Knowing that it's a Console Application, Invoke and BeginInvoke solution did not work. I also tried Events and EventHandler.

I hope my problem won't be misunderstood. Here's the code and the output.

// storing the callback as a field to make sure the garbage collector do not move it
// while being used in managed code, this is easier than using GCHandle 
static WinEventDelegate procDelegate = new Native.WinEventDelegate(WinEventProc);

static void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, 
    int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
    {
        Console.WriteLine("callback, tid = " + Thread.CurrentThread.ManagedThreadId);
    }

ManagementEventWatcher processStartEvent = new ManagementEventWatcher("SELECT * FROM Win32_ProcessStartTrace");

void processStartEvent_EventArrived(object sender, EventArrivedEventArgs e)
{
    string processName = e.NewEvent.Properties["ProcessName"].Value.ToString();
    int processID = Convert.ToInt32(e.NewEvent.Properties["ProcessID"].Value);
    Process process = Process.GetProcessById(processID);
    IntPtr hook = SetWinEventHook(eventId, eventId, IntPtr.Zero, procDelegate, (uint)process.Id, 
            GetWindowThreadProcessId(process.MainWindowHandle, IntPtr.Zero),
            Native.WINEVENT_OUTOFCONTEXT | Native.WINEVENT_SKIPOWNPROCESS | Native.WINEVENT_SKIPOWNTHREAD); 
    if (hook == IntPtr.Zero)  Console.WriteLine("Hooking failed");
    Console.WriteLine("event, tid = " + Thread.CurrentThread.ManagedThreadId);
}

void watchProcess()
{
    processStartEvent.EventArrived += new EventArrivedEventHandler(processStartEvent_EventArrived);
    processStartEvent.Start();
}

static void Main(string[] args)
{
        Console.WriteLine("main, tid = " + Thread.CurrentThread.ManagedThreadId);
        watchProcess(); 
        MessageBox.Show("Message loop");          
}

Output :

main, tid = 1
event, tid = 4 // repeated as many times as new processes created

解决方案

Have had the same problem. Use Invoke method from any form:

            this.Invoke(new MethodInvoker(() => StartEventListener()));

Regards

这篇关于力SetWinEventHook是从主线程调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆