0

我正在尝试读取活动应用程序中菜单项的标签名称并将它们存储在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;
4

3 回答 3

1

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

您可以使用VirtualAllocEx,WriteProcessMemory并在另一个进程的地址空间中ReadProcessMemory 分配、写入和读取结构的实例。MENUITEMINFO这是使该机制发挥作用的唯一希望。使用 websearch 可以找到很多示例来说明该技术。

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

于 2013-06-10T13:05:02.523 回答
1

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

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

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

确保之后释放内存!

于 2013-06-10T06:12:49.857 回答
0

尝试更换

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

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

Win32 API MENUITEMINFOA文档指出

MFT_STRINGMIIM_STRING取代。

于 2020-10-17T12:57:14.730 回答