Korzystam z mechanizmu PInvoke, w tym celu napisałem prostą klasę dziedziczącą po SafeHandle
:
using Microsoft.Win32.SafeHandles;
using System.Security;
namespace Hermeslogger.Core
{
internal sealed class SafeWinEventHookHandle : SafeHandleZeroOrMinusOneIsInvalid
{
public SafeWinEventHookHandle() : base(true)
{
}
[SecurityCritical]
protected override bool ReleaseHandle()
{
return NativeMethods.UnhookWinEvent(this.handle);
}
}
}
Tutaj moja definicja PInvoke:
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Hermeslogger.Core
{
internal delegate void WinEventProcDef(SafeWinEventHookHandle winEventHook, int eventId, IntPtr windowHandle, int objectId, int childId, int eventThread, int eventTime);
internal static class NativeMethods
{
public const int EVENT_OBJECT_FOCUS = 0x8005;
public const int EVENT_SYSTEM_FOREGROUND = 0x0003;
public const int WINEVENT_OUTOFCONTEXT = 0x0000;
public const int WM_DESTROY = 0x0002;
[DllImport(ExternDll.User32, CharSet = CharSet.Auto)]
public static extern IntPtr GetForegroundWindow();
[DllImport(ExternDll.User32, CharSet = CharSet.Auto)]
public static extern int GetWindowText(HandleRef windowHandle, StringBuilder text, int maxLength);
[DllImport(ExternDll.User32, CharSet = CharSet.Auto)]
public static extern int GetWindowTextLength(HandleRef windowHandle);
[DllImport(ExternDll.User32, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr window, int message, IntPtr wParam, IntPtr lParam);
[DllImport(ExternDll.User32)]
public static extern SafeWinEventHookHandle SetWinEventHook(int eventMin, int eventMax, IntPtr instance, WinEventProcDef winEventProc, uint processId, uint threadId, int flags);
[DllImport(ExternDll.User32)]
public static extern bool UnhookWinEvent(IntPtr winEventHook);
}
}
Teraz podczas wykonania kodu:
NativeMethods.SetWinEventHook(NativeMethods.EVENT_OBJECT_FOCUS, NativeMethods.EVENT_OBJECT_FOCUS, IntPtr.Zero, this.winEventProc, 0, 0, NativeMethods.WINEVENT_OUTOFCONTEXT);
NativeMethods.SetWinEventHook(NativeMethods.EVENT_SYSTEM_FOREGROUND, NativeMethods.EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, this.winEventProc, 0, 0, NativeMethods.WINEVENT_OUTOFCONTEXT);
Otrzymuje wyjątek:
Cannot marshal 'parameter #1': SafeHandles cannot be marshaled from unmanaged to managed.
Czy przyczyna leży w złej deklaracji mojego SafeHandle? Czy może gdzieś indziej