为什么GetMenuItemInfo不能工作?

本文关键字:工作 不能 GetMenuItemInfo 为什么 | 更新日期: 2023-09-27 18:17:32

我正在尝试读取活动应用程序中菜单项的标签名称并将它们存储在List<String>中。

不幸的是,dwTypeData总是返回null。为什么会这样?

            List<string> ls = new List<string>();
        IntPtr hMenu = Win32.GetMenu(hWnd);
            if (hMenu.ToInt32() != 0)
            {
                for (int i = Win32.GetMenuItemCount(hMenu); i >= 0; i--)
                {
                    try
                    {
                        uint MIIM_STRING = 0x00000040;
                        uint MFT_STRING = 0x00000000;
                        uint MIIM_TYPE = 0x00000010;
                        Win32.MENUITEMINFO mif = new Win32.MENUITEMINFO();
                        mif.cbSize = (uint)Marshal.SizeOf(typeof(Win32.MENUITEMINFO));
                        mif.fMask = MIIM_TYPE;
                        mif.fType = MFT_STRING;
                        mif.cch = 256;
                        mif.dwTypeData = "";
                        Win32.GetMenuItemInfo(hMenu, (uint)i, true, ref mif); //To load cch into memory
                        Win32.GetMenuItemInfo(hMenu, (uint)i, true, ref mif); //To fill dwTypeData
                        ls.Add(mif.dwTypeData);
                    }
                    catch { }
                }
            }
        return ls;

为什么GetMenuItemInfo不能工作?

a)循环应为for (int i = Win32.GetMenuItemCount(hMenu) - 1; i >= 0; i--)

b)在第一次调用GetMenuItemInfo()之前,您需要将mif.dwTypeData设置为NULL(零)

c)在第二次调用GetMenuItemInfo()之前,mif.dwTypeData应该指向一个分配了mif.cch + 1大小的缓冲区——参见MSDN文档

确保你释放内存之后!

您的问题是您试图在不同的进程中执行此操作。当调用GetMenuItemInfo时,传递的是MENUITEMINFO结构体的地址。但是这个地址只在你的进程中有效。因为每个进程都有自己的私有虚拟内存空间,所以你发送的指针在其他进程中是没有意义的。

您可以使用VirtualAllocEx, WriteProcessMemoryReadProcessMemory在另一个进程的地址空间中分配,写入和读取MENUITEMINFO结构体的实例。这是让这个机制工作的唯一希望。有很多使用网络搜索的例子来说明这个技术。

但是,我不建议你那样做。您应该使用一个标准的自动化接口来解决实际问题。例如UIAutomation。

尝试替换

mif.fMask = MIIM_TYPE;
mif.fType = MFT_STRING;

mif.fMask = MIIM_FTYPE;
mif.fType = MIIM_STRING;

Win32 API MENUITEMINFOA文档说明

MFT_STRING MIIM_STRING