如何使用 ReadProcessMemory 获取托盘按钮文本

Posted

技术标签:

【中文标题】如何使用 ReadProcessMemory 获取托盘按钮文本【英文标题】:how to get the tray button text wiht ReadProcessMemory 【发布时间】:2012-11-10 15:44:48 【问题描述】:

我想用 C# 获取 windows7(64 位)上的所有托盘图标,但是当我使用 windows api“ReadProcessMemory”时,无法识别托盘按钮文本。 下面的代码

        IntPtr pid = IntPtr.Zero;
        IntPtr ipHandle = IntPtr.Zero; 
        IntPtr lTextAdr = IntPtr.Zero; 

        IntPtr ipTray = TrayToolbarWindow32();

        WinApiHelper.GetWindowThreadProcessId(ipTray, ref pid);
        if (pid.Equals(0))
            return iconList;

        IntPtr hProcess = WinApiHelper.OpenProcess(WinApiHelper.PROCESS_ALL_ACCESS | WinApiHelper.PROCESS_VM_OPERATION | WinApiHelper.PROCESS_VM_READ | WinApiHelper.PROCESS_VM_WRITE, IntPtr.Zero, pid);

        IntPtr lAddress = WinApiHelper.VirtualAllocEx(hProcess, 0, 4096, WinApiHelper.MEM_COMMIT, WinApiHelper.PAGE_READWRITE);


        int lButton = WinApiHelper.SendMessage(ipTray, WinApiHelper.TB_BUTTONCOUNT, 0, 0);

        for (int i = 0; i < lButton; i++)
        

            WinApiHelper.SendMessage(ipTray, WinApiHelper.TB_GETBUTTON, i, lAddress);


            WinApiHelper.ReadProcessMemory(hProcess, (IntPtr)(lAddress.ToInt32() + 16), ref lTextAdr, 4, 0);

            if (!lTextAdr.Equals(-1))
            
                byte[] buff = new byte[ 1024 ];

                WinApiHelper.ReadProcessMemory(hProcess, lTextAdr, buff, 1024, 0);
                string title = System.Text.ASCIIEncoding.Unicode.GetString(buff);

和api声明

    [DllImport("kernel32", EntryPoint = "ReadProcessMemory")]
    public static extern int ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref IntPtr lpBuffer, int nSize, int lpNumberOfBytesWritten);

    [DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
    public static extern bool ReadProcessMemoryEx(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, IntPtr size, out IntPtr lpNumberOfBytesRead);

    [DllImport("kernel32", EntryPoint = "ReadProcessMemory")]
    public static extern int ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] lpBuffer, int nSize, int lpNumberOfBytesWritten);

    [DllImport("kernel32.dll")]
    public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, UIntPtr nSize, IntPtr lpNumberOfBytesRead);

问题来了

string title = System.Text.ASCIIEncoding.Unicode.GetString(buff);

转换时,字符串“title”无法识别,可能是这样的

ǎ\0\0\0\0Д\0\0à\0\0ƿ\r\0\0\0\0\0\0\0\0\0\0D:\\Tools\\ESET Smart Security\\egui.exe\0\0\0\0\0\0\0\0\0\0\0\0\0\

我不知道为什么,求助。

【问题讨论】:

此代码无法在 64 位操作系统上正常运行。 【参考方案1】:

您可能需要考虑自己在做什么。 ReadProcessMemory 是为调试器设计的调试函数,需要SeDebugPrivilege,所以我希望你正在编写一个调试器。忽略我在考虑以非调试能力使用这些功能时的不适,您正在泄漏您分配的缓冲区并要求您的应用程序以管理员身份运行。

如果此应用程序仅用于您自己的目的而不用于其他任何人,请查看相关问题Systray Access,因为似乎有单独的 TB_GETBUTTONTEXT 消息。我想您实际上是在接收按钮数据,而不是复制内存中的文本,从而导致问题。

【讨论】:

以上是关于如何使用 ReadProcessMemory 获取托盘按钮文本的主要内容,如果未能解决你的问题,请参考以下文章

Win32 ReadProcessMemory API 的问题

ReadProcessMemory 整个过程

获取其他进程的命令行(ReadProcessMemory其它进程的PPROCESS_PARAMETERS和PEB结构体)

我可以使用 ReadProcessMemory 在 Windows 中读取进程的程序内存吗?

ReadProcessMemory函数的参数如何设置

确定外部进程的主线程 ID(ReadProcessMemory - 错误 299)