python - 使用 Python 从另一个应用程序中提取 ListView 项

标签 python listview pywin32 syslistview32

我有一个带有 ListView ('SysListView32') 控件的应用程序,我想从中提取数据。该控件有 4 列,只有文本数据。

我一直在玩以下几行(在网上某处找到):

VALUE_LENGTH = 256
bufferlength_int=struct.pack('i', VALUE_LENGTH)
count = win32gui.SendMessage(TargetHwnd, commctrl.LVM_GETITEMCOUNT, 0, 0)
for ItemIndex in range(count):
    valuebuffer = array.array('c',bufferlength_int + " " * (VALUE_LENGTH - len(bufferlength_int)))
    ListItems = win32gui.SendMessage(TargetHwnd, commctrl.LVM_GETITEMTEXT, ItemIndex, valuebuffer)

[上面的代码可能不是完全可执行的,因为我从不相关的东西中删除了它。但要点肯定在这里。]

这似乎运行正常,但我一定是做错了什么 - 作为返回,我得到了各种大部分为零的数据缓冲区,但没有我正在寻找的实际文本内容。

有什么建议吗?

谢谢,
与那滩

最佳答案

好吧,事实证明我有几个地方错了。然而,可以通过在目标进程内分配内存、在那里构建所需的结构 (LVITEM)、发送消息并从在所述进程中分配的缓冲区中读回结果来实现。

为了完整起见,我附上了一个代码示例,用于在给定控件的窗口句柄的情况下从外部进程读取 SysListView32 项。

from win32con import PAGE_READWRITE, MEM_COMMIT, MEM_RESERVE, MEM_RELEASE,\
    PROCESS_ALL_ACCESS
from commctrl import LVM_GETITEMTEXT, LVM_GETITEMCOUNT

import struct
import ctypes
import win32api
import win32gui

GetWindowThreadProcessId = ctypes.windll.user32.GetWindowThreadProcessId
VirtualAllocEx = ctypes.windll.kernel32.VirtualAllocEx
VirtualFreeEx = ctypes.windll.kernel32.VirtualFreeEx
OpenProcess = ctypes.windll.kernel32.OpenProcess
WriteProcessMemory = ctypes.windll.kernel32.WriteProcessMemory
ReadProcessMemory = ctypes.windll.kernel32.ReadProcessMemory
memcpy = ctypes.cdll.msvcrt.memcpy


def readListViewItems(hwnd, column_index=0):

    # Allocate virtual memory inside target process
    pid = ctypes.create_string_buffer(4)
    p_pid = ctypes.addressof(pid)
    GetWindowThreadProcessId(hwnd, p_pid) # process owning the given hwnd
    hProcHnd = OpenProcess(PROCESS_ALL_ACCESS, False, struct.unpack("i",pid)[0])
    pLVI = VirtualAllocEx(hProcHnd, 0, 4096, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE)
    pBuffer = VirtualAllocEx(hProcHnd, 0, 4096, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE)

    # Prepare an LVITEM record and write it to target process memory
    lvitem_str = struct.pack('iiiiiiiii', *[0,0,column_index,0,0,pBuffer,4096,0,0])
    lvitem_buffer = ctypes.create_string_buffer(lvitem_str)
    copied = ctypes.create_string_buffer(4)
    p_copied = ctypes.addressof(copied)
    WriteProcessMemory(hProcHnd, pLVI, ctypes.addressof(lvitem_buffer), ctypes.sizeof(lvitem_buffer), p_copied)

    # iterate items in the SysListView32 control
    num_items = win32gui.SendMessage(hwnd, LVM_GETITEMCOUNT)
    item_texts = []
    for item_index in range(num_items):
        win32gui.SendMessage(hwnd, LVM_GETITEMTEXT, item_index, pLVI)
        target_buff = ctypes.create_string_buffer(4096)
        ReadProcessMemory(hProcHnd, pBuffer, ctypes.addressof(target_buff), 4096, p_copied)
        item_texts.append(target_buff.value)

    VirtualFreeEx(hProcHnd, pBuffer, 0, MEM_RELEASE)
    VirtualFreeEx(hProcHnd, pLVI, 0, MEM_RELEASE)
    win32api.CloseHandle(hProcHnd)
    return item_texts

关于python - 使用 Python 从另一个应用程序中提取 ListView 项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1872480/

相关文章:

python - "Incorrect number of bindings supplied"cPython 3.5 SQLite3 VS15

python - 从段落美丽汤中获取内容(全文字)

python - PyCharm:msvcrt.kbhit() 和 msvcrt.getch() 不起作用?

android - 使用 addView 而不是 listView

android - 自定义可更新ListView - Android 开发

python - windows:在双击标题栏时禁用最大化窗口,并在单击任务栏时最小化窗口

python - 如何在箱线图中显示 Pandas DataFrame 的最后一行

android - 使用 ListFragment 时无法引用 ListView

python - 使用 tkinter 从剪贴板复制而不显示窗口

events - 如何在python中捕获打印机事件