private static void EnumMenuItems( Shell32.IContextMenu cMenu, HMENU hMenu, List <Win32ContextMenuItem> menuItemsResult, Func <string, bool> itemFilter = null) { var itemCount = User32.GetMenuItemCount(hMenu); var mii = new User32.MENUITEMINFO(); mii.cbSize = (uint)Marshal.SizeOf(mii); mii.fMask = User32.MenuItemInfoMask.MIIM_BITMAP | User32.MenuItemInfoMask.MIIM_FTYPE | User32.MenuItemInfoMask.MIIM_STRING | User32.MenuItemInfoMask.MIIM_ID | User32.MenuItemInfoMask.MIIM_SUBMENU; for (uint ii = 0; ii < itemCount; ii++) { var menuItem = new ContextMenuItem(); var container = new SafeCoTaskMemString(512); mii.dwTypeData = (IntPtr)container; mii.cch = (uint)container.Capacity - 1; // https://devblogs.microsoft.com/oldnewthing/20040928-00/?p=37723 var retval = User32.GetMenuItemInfo(hMenu, ii, true, ref mii); if (!retval) { container.Dispose(); continue; } menuItem.Type = (MenuItemType)mii.fType; menuItem.ID = (int)(mii.wID - 1); // wID - idCmdFirst if (menuItem.Type == MenuItemType.MFT_STRING) { Debug.WriteLine("Item {0} ({1}): {2}", ii, mii.wID, mii.dwTypeData); menuItem.Label = mii.dwTypeData; menuItem.CommandString = GetCommandString(cMenu, mii.wID - 1); if (itemFilter != null && (itemFilter(menuItem.CommandString) || itemFilter(menuItem.Label))) { // Skip items implemented in UWP container.Dispose(); continue; } if (mii.hbmpItem != HBITMAP.NULL && !Enum.IsDefined(typeof(HBITMAP_HMENU), ((IntPtr)mii.hbmpItem).ToInt64())) { using var bitmap = Win32API.GetBitmapFromHBitmap(mii.hbmpItem); if (bitmap != null) { byte[] bitmapData = (byte[])new ImageConverter().ConvertTo(bitmap, typeof(byte[])); menuItem.IconBase64 = Convert.ToBase64String(bitmapData, 0, bitmapData.Length); } } if (mii.hSubMenu != HMENU.NULL) { Debug.WriteLine("Item {0}: has submenu", ii); var subItems = new List <Win32ContextMenuItem>(); try { (cMenu as Shell32.IContextMenu2)?.HandleMenuMsg((uint)User32.WindowMessage.WM_INITMENUPOPUP, (IntPtr)mii.hSubMenu, new IntPtr(ii)); } catch (NotImplementedException) { // Only for dynamic/owner drawn? (open with, etc) } EnumMenuItems(cMenu, mii.hSubMenu, subItems, itemFilter); menuItem.SubItems = subItems; Debug.WriteLine("Item {0}: done submenu", ii); } } else { Debug.WriteLine("Item {0}: {1}", ii, mii.fType.ToString()); } container.Dispose(); menuItemsResult.Add(menuItem); } }