Die Community zu .NET und Classic VB.
Menü

VB 5/6-Tipp 0771: Text von fremder ListView und ListViewHeader auslesen

 von 

Beschreibung 

Mit SendMessage lassen sich einige Informationen von einer fremden ListView auslesen. Nur der Text eines ListViewItems bzw. einen ListViewHeaderItems nicht. Dieses Beispiel zeigt wie es doch geht.

Schwierigkeitsgrad:

Schwierigkeitsgrad 2

Verwendete API-Aufrufe:

CloseHandle, FindWindowA (FindWindow), FindWindowExA (FindWindowEx), GetWindowThreadProcessId, OpenProcess, ReadProcessMemory, SendMessageA (SendMessage), VirtualAllocEx, VirtualFreeEx, WriteProcessMemory

Download:

Download des Beispielprojektes [4.99 KB]

'Dieser Quellcode stammt von http://www.activevb.de
'und kann frei verwendet werden. Für eventuelle Schäden
'wird nicht gehaftet.

'Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
'Ansonsten viel Spaß und Erfolg mit diesem Source!

'----------- Anfang Projektdatei ReadListView.vbp -----------
' Die Komponente 'Microsoft Windows Common Controls 6.0 (mscomctl.ocx)' wird benötigt.

'------- Anfang Formular "frmMain" alias frmMain.frm  -------
' Steuerelement: Schaltfläche "Command1"
' Steuerelement: Listenanzeigesteuerungselement "ListView1"
Option Explicit

' Starten Sie zuerst den Taskmanager von Windows und wechseln
' Sie dann auf die Registerkarte "Prozesse". Klicken Sie dann
' auf den Button "Read Taskmanager ListView".

Private Sub Form_Load()

    Me.ScaleMode = vbPixels
    
End Sub

Private Sub Command1_Click()

    Dim hListView As Long
    
    ' Handle des SysListView32 im Taskmanager ermitteln
    hListView = FindTaskmanagerListView
    
    ' ist ein Handle vorhanden
    If hListView <> 0 Then
    
        ' ListView auslesen
        Call ReadFromListView(hListView)
        
    End If
    
End Sub

' SysListView32 des Taskmanager finden
Private Function FindTaskmanagerListView() As Long

    Dim lngWnd0 As Long
    Dim lngWnd1 As Long
    Dim lngWnd2 As Long
    Dim lngWnd3 As Long
    Dim lngWnd4 As Long
    
    lngWnd0 = FindWindow("#32770", "Windows Task-Manager")
    
    If lngWnd0 <> 0 Then
    
        lngWnd1 = FindWindowEx(lngWnd0, 0&, "#32770", vbNullString)
        
        If lngWnd1 <> 0 Then
        
            lngWnd2 = FindWindowEx(lngWnd1, 0&, "SysListView32", _
                "Prozesse")
                
            If lngWnd2 <> 0 Then
            
                FindTaskmanagerListView = lngWnd2
                
            End If
        End If
    End If
    
End Function

' ListView auslesen
Private Sub ReadFromListView(ByVal hListViewWnd As Long)

    Dim xItem As ListItem
    Dim xColumn As ColumnHeader
    Dim lngCol As Long
    Dim lngRow As Long
    Dim lngColCount As Long
    Dim lngRowCount As Long
    Dim lngItem As Long
    Dim lngHeader As Long
    
    ' alle Items löschen
    ListView1.ListItems.Clear
    ListView1.ColumnHeaders.Clear
    
    ' Reportansicht
    ListView1.View = lvwReport
    
    ' Handle des ListView-Headers ermitteln
    lngHeader = SendMessage(hListViewWnd, LVM_GETHEADER, 0, 0)
    
    ' ist ein Handle vorhanden
    If lngHeader <> 0 Then
    
        ' Anzahl der Headerelemente (Spalten) auslesen
        lngColCount = SendMessage(lngHeader, HDM_GETITEMCOUNT, 0&, 0&)
        
        ' alle Headerelemente durchlaufen
        For lngItem = 0 To lngColCount - 1
        
            ' Header anlegen
            Set xColumn = ListView1.ColumnHeaders.Add(, , _
                GetHeaderItemString(lngHeader, lngItem))
                
            ' Columnbreite auslesen und für unsere ListView setzen
            xColumn.Width = SendMessage(hListViewWnd, LVM_GETCOLUMNWIDTH, _
                lngItem, 0)
                
        Next lngItem
        
    End If
    
    ' Anzahl der ListView-Elemente (Zeilen) auslesen
    lngRowCount = SendMessage(hListViewWnd, LVM_GETITEMCOUNT, 0&, 0&)
    
    ' alle Zeilen durchlaufen
    For lngRow = 0 To lngRowCount - 1
    
        ' alle Spalten durchlaufen
        For lngCol = 0 To lngColCount - 1
        
            ' Spalte 0
            If lngCol = 0 Then
            
                ' Item in der ListView anlegen
                Set xItem = ListView1.ListItems.Add(, , _
                    GetListViewItemString(hListViewWnd, lngRow, lngCol))
                    
            Else
            
                ' SubItems ausfüllen
                xItem.SubItems(lngCol) = GetListViewItemString( _
                    hListViewWnd, lngRow, lngCol)
                    
            End If
            
        Next lngCol
    Next lngRow
    
End Sub

'-------- Ende Formular "frmMain" alias frmMain.frm  --------
'--- Anfang Modul "modReadListView" alias modReadListView.bas ---
Option Explicit

' ---=== Root Const ===---
Private Const HDM_FIRST As Long = &H1200
Private Const LVM_FIRST As Long = &H1000

' ---=== Public Const ===---
Public Const HDM_GETITEMCOUNT As Long = (HDM_FIRST + 0)
Public Const LVM_GETITEMCOUNT As Long = (LVM_FIRST + 4)
Public Const LVM_GETCOLUMNWIDTH As Long = (LVM_FIRST + 29)
Public Const LVM_GETHEADER As Long = (LVM_FIRST + 31)

' ---=== Private Const ===---
Private Const HDI_TEXT As Long = &H2
Private Const HDM_GETITEM As Long = (HDM_FIRST + 3)
Private Const LVIF_TEXT As Long = &H1
Private Const LVM_GETITEM As Long = (LVM_FIRST + 5)
Private Const MAX_LVMSTRING As Long = 255
Private Const MEM_COMMIT As Long = &H1000
Private Const MEM_RELEASE As Long = &H8000
Private Const MEM_RESERVE As Long = &H2000
Private Const PAGE_READWRITE As Long = &H4
Private Const PROCESS_VM_OPERATION As Long = &H8
Private Const PROCESS_VM_READ As Long = &H10
Private Const PROCESS_VM_WRITE As Long = &H20

' ---=== Type ===---
Private Type LVITEM
    mask As Long
    iItem As Long
    iSubItem As Long
    state As Long
    stateMask As Long
    pszText As Long
    cchTextMax As Long
    iImage As Long
    lParam As Long
    iIndent As Long
End Type

Private Type HDITEM
    mask As Long
    cxy As Long
    pszText As Long
    hbm As Long
    cchTextMax As Long
    fmt As Long
    lParam As Long
    iImage As Long
    iOrder As Long
    Type As Long
    pvFilter As Long
    state As Long
End Type

' ---=== KERNEL32 ===---
Private Declare Function CloseHandle Lib "kernel32.dll" ( _
                         ByVal hObject As Long) As Long
                         
Private Declare Function OpenProcess Lib "kernel32.dll" ( _
                         ByVal dwDesiredAccess As Long, _
                         ByVal bInheritHandle As Long, _
                         ByVal dwProcessId As Long) As Long
                         
Private Declare Function ReadProcessMemory Lib "kernel32.dll" ( _
                         ByVal hProcess As Long, _
                         ByVal lpBaseAddress As Long, _
                         ByRef lpBuffer As Any, _
                         ByVal nSize As Long, _
                         ByRef lpNumberOfBytesWritten As Long) As Long
                         
Private Declare Function VirtualAllocEx Lib "kernel32.dll" ( _
                         ByVal hProcess As Long, _
                         ByVal lpAddress As Long, _
                         ByVal wSize As Long, _
                         ByVal flAllocationType As Long, _
                         ByVal flProtect As Long) As Long
                         
Private Declare Function VirtualFreeEx Lib "kernel32.dll" ( _
                         ByVal hProcess As Long, _
                         ByVal lpAddress As Long, _
                         ByVal dwSize As Long, _
                         ByVal dwFreeType As Long) As Long
                         
Private Declare Function WriteProcessMemory Lib "kernel32.dll" ( _
                         ByVal hProcess As Long, _
                         ByVal lpBaseAddress As Long, _
                         ByRef lpBuffer As Any, _
                         ByVal nSize As Long, _
                         ByRef lpNumberOfBytesWritten As Long) As Long
                         
' ---=== USER32 ===---
Public Declare Function FindWindow Lib "user32.dll" _
                        Alias "FindWindowA" ( _
                        ByVal lpClassName As String, _
                        ByVal lpWindowName As String) As Long
                        
Public Declare Function FindWindowEx Lib "user32.dll" _
                        Alias "FindWindowExA" ( _
                        ByVal hWnd1 As Long, _
                        ByVal hWnd2 As Long, _
                        ByVal lpsz1 As String, _
                        ByVal lpsz2 As String) As Long
                        
Private Declare Function GetWindowThreadProcessId Lib "user32.dll" ( _
                         ByVal hwnd As Long, _
                         ByRef lpdwProcessId As Long) As Long
                         
Public Declare Function SendMessage Lib "user32.dll" _
                        Alias "SendMessageA" ( _
                        ByVal hwnd As Long, _
                        ByVal wMsg As Long, _
                        ByVal wParam As Long, _
                        ByRef lParam As Any) As Long
                        
Public Function GetListViewItemString(ByVal hListView As Long, Optional _
    ByVal Row As Long = 0, Optional ByVal Col As Long = 0) As String
    
    Dim hProcess As Long
    Dim lngLvItemPtr As Long
    Dim lngProcessID As Long
    Dim retStr As String
    Dim bytBuff() As Byte
    Dim tLVITEM As LVITEM
    
    ' ProzessID vom ListView ermitteln
    If GetWindowThreadProcessId(hListView, lngProcessID) Then
    
        ' Handle auf den Prozess öffnen
        hProcess = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or _
            PROCESS_VM_WRITE, False, lngProcessID)
            
        ' ist ein Handle vorhanden
        If hProcess <> 0 Then
        
            ' Einen ausreichend großen Speicherbereich im Prozess
            ' reservieren. Größe der Struktur LVITEM + maximale
            ' Größe des Strings. Der String soll dann im Speicher
            ' hinter der Stuktur abgelegt werden.
            lngLvItemPtr = VirtualAllocEx(hProcess, 0&, Len(tLVITEM) + _
                MAX_LVMSTRING, MEM_COMMIT Or MEM_RESERVE, PAGE_READWRITE)
                
            ' ist ein Zeiger auf den Speicherbereich vorhanden
            If lngLvItemPtr <> 0 Then
            
                ' LVITEM initialisieren
                With tLVITEM
                
                    ' nur den String auslesen
                    .mask = LVIF_TEXT
                    
                    ' Zeile
                    .iItem = Row
                    
                    ' Spalte
                    .iSubItem = Col
                    
                    ' Zeiger auf den Speicherbereich + Größe der
                    ' Struktur LVITEM. Dort soll dann der String
                    ' abgelegt werden.
                    .pszText = lngLvItemPtr + Len(tLVITEM)
                    
                    ' maximale Größe des Strings
                    .cchTextMax = MAX_LVMSTRING
                    
                End With
                
                ' LVITEM in den Speicher an angegebener Speicheradresse
                ' schreiben
                If WriteProcessMemory(hProcess, lngLvItemPtr, tLVITEM, _
                    Len(tLVITEM), ByVal 0&) Then
                    
                    ' ListViewItem-Daten auslesen so wie die Daten an
                    ' angegebener Speicheradresse vorliegen
                    If SendMessage(hListView, LVM_GETITEM, 0&, ByVal _
                        lngLvItemPtr) Then
                        
                        ' ByteArray zur Aufnahme des Strings dimensionieren
                        ReDim bytBuff(0 To MAX_LVMSTRING)
                        
                        ' String (ByteArray) vom Speicher auslesen. Die
                        ' Speicheradresse ist die wie in LVITEM.pszText
                        ' angegebene Adresse.
                        If ReadProcessMemory(hProcess, lngLvItemPtr + _
                            Len(tLVITEM), bytBuff(0), MAX_LVMSTRING, _
                            ByVal 0&) Then
                            
                            ' ByteArray konvertieren
                            retStr = StrConv(bytBuff, vbUnicode)
                            
                            ' String bei vbNullChar abschneiden
                            retStr = Left$(retStr, InStr(1, retStr, _
                                vbNullChar) - 1)
                                
                            ' String zurück geben
                            GetListViewItemString = retStr
                            
                        End If
                    End If
                End If
                
                ' reservierten Speicher wieder freigeben
                Call VirtualFreeEx(hProcess, lngLvItemPtr, 0&, MEM_RELEASE)
                
            End If
            
            ' Handle auf den Prozess schließen
            Call CloseHandle(hProcess)
            
        End If
    End If
    
End Function

Public Function GetHeaderItemString(ByVal hHeader As Long, Optional ByVal _
    Item As Long = 0) As String
    
    Dim hProcess As Long
    Dim lngHdrItemPtr As Long
    Dim lngProcessID As Long
    Dim retStr As String
    Dim bytBuff() As Byte
    Dim tHDITEM As HDITEM
    
    ' ProzessID vom Header ermitteln
    If GetWindowThreadProcessId(hHeader, lngProcessID) Then
    
        ' Handle auf den Prozess öffnen
        hProcess = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or _
            PROCESS_VM_WRITE, False, lngProcessID)
            
        ' ist ein Handle vorhanden
        If hProcess <> 0 Then
        
            ' Einen ausreichend großen Speicherbereich im Prozess
            ' reservieren. Größe der Struktur HDITEM + maximale
            ' Größe des Strings. Der String soll dann im Speicher
            ' hinter der Stuktur abgelegt werden.
            lngHdrItemPtr = VirtualAllocEx(hProcess, 0&, Len(tHDITEM) + _
                MAX_LVMSTRING, MEM_COMMIT Or MEM_RESERVE, PAGE_READWRITE)
                
            ' ist ein Zeiger auf den Speicherbereich vorhanden
            If lngHdrItemPtr <> 0 Then
            
                ' HDITEM initialisieren
                With tHDITEM
                
                    ' nur den String auslesen
                    .mask = HDI_TEXT
                    
                    ' Zeiger auf den Speicherbereich + Größe der
                    ' Struktur LVITEM. Dort soll dann der String
                    ' abgelegt werden.
                    .pszText = lngHdrItemPtr + Len(tHDITEM)
                    
                    ' maximale Größe des Strings
                    .cchTextMax = MAX_LVMSTRING
                    
                End With
                
                ' HDITEM in den Speicher an angegebener Speicheradresse
                ' schreiben
                If WriteProcessMemory(hProcess, lngHdrItemPtr, tHDITEM, _
                    Len(tHDITEM), ByVal 0&) Then
                    
                    ' HeaderItem-Daten auslesen so wie die Daten an
                    ' angegebener Speicheradresse vorliegen
                    If SendMessage(hHeader, HDM_GETITEM, Item, ByVal _
                        lngHdrItemPtr) Then
                        
                        ' ByteArray zur Aufnahme des Strings dimensionieren
                        ReDim bytBuff(0 To MAX_LVMSTRING)
                        
                        ' String (ByteArray) vom Speicher auslesen. Die
                        ' Speicheradresse ist die wie in HDITEM.pszText
                        ' angegebene Adresse.
                        If ReadProcessMemory(hProcess, lngHdrItemPtr + _
                            Len(tHDITEM), bytBuff(0), MAX_LVMSTRING, _
                            ByVal 0&) Then
                            
                            ' ByteArray konvertieren
                            retStr = StrConv(bytBuff, vbUnicode)
                            
                            ' String bei vbNullChar abschneiden
                            retStr = Left$(retStr, InStr(1, retStr, _
                                vbNullChar) - 1)
                                
                            ' String zurück geben
                            GetHeaderItemString = retStr
                            
                        End If
                    End If
                End If
                
                ' reservierten Speicher wieder freigeben
                Call VirtualFreeEx(hProcess, lngHdrItemPtr, 0&, _
                    MEM_RELEASE)
                    
            End If
            
            ' Handle auf den Prozess schließen
            Call CloseHandle(hProcess)
            
        End If
    End If
    
End Function


'--- Ende Modul "modReadListView" alias modReadListView.bas ---
'------------ Ende Projektdatei ReadListView.vbp ------------

Tipp-Kompatibilität:

Windows/VB-VersionWin32sWin95Win98WinMEWinNT4Win2000WinXP
VB4
VB5
VB6

Hat dieser Tipp auf Ihrem Betriebsystem und mit Ihrer VB-Version funktioniert?

Ja, funktioniert!

Nein, funktioniert nicht bei mir!

VB-Version:

Windows-Version:

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.