4

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)

[上記のコードは、無関係なものを削除したため、完全には実行できない可能性があります。しかし要点は確かにここにあります。]

これは問題なく動作するようですが、私は何か間違ったことをしているに違いありません - あらゆる種類のほとんどゼロのデータ バッファーが返され、探していた実際のテキスト コンテンツは何もありません。

助言がありますか?

ありがとう、
よなたん

4

2 に答える 2

7

さて、私はそこのいくつかの点で間違っていたことがわかりました。ただし、ターゲットプロセス内にメモリを割り当て、そこで必要な構造体(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
于 2009-12-12T15:06:24.143 に答える
1

コントロールがコードと同じプロセスにある場合は、機能するはずです。(「別のアプリケーション」が示唆するように)別のプロセスにある場合、これは機能しません(または少なくとも機能しないはずです)。エラーコードを確認してください。「許可が拒否されました」という行に沿って何かが表示されるはずです: アプリケーションはお互いのメモリを参照できません。

于 2009-12-09T08:56:01.703 に答える