.NET Compact Framework 2.0では関数ポインタのマーシャリングがサポートされましたが、引数や戻り値の型に制限があります。boolは変換できないためNotSupportedExceptionになります。boolの代わりにintを使えば問題ありません。
このことを知らずにP/InvokeでEnumWindows()を使おうとしてハマりました。以下に正常動作する例を示します。 "coredll.dll" を "user32.dll" に変更すればPCでも使用できます。
[UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate int EnumWindowsProc(IntPtr hWnd, int lParam); [DllImport("coredll.dll")] public static extern int EnumWindows(EnumWindowsProc lpEnumFunc, int lParam); [DllImport("coredll.dll")] public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId); [DllImport("coredll.dll", CharSet = CharSet.Unicode)] public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); public static IntPtr GetWindowHandle(string className) { var ret = IntPtr.Zero; var curpid = Process.GetCurrentProcess().Id; EnumWindows((hWnd, lParam) => { int pid; GetWindowThreadProcessId(hWnd, out pid); if (pid == curpid) { var sb = new StringBuilder(64); GetClassName(hWnd, sb, sb.Capacity); if (sb.ToString() == className) { ret = hWnd; return 0; } } return 1; }, 0); return ret; }
クロージャのマーシャリングはサンクで実装されているようです。