none
Problema al clonar un Listview externo en sistema operativo de 64 bits RRS feed

  • Pregunta

  • Hola. Estoy utilizando una funcion que clona en mi programa, el listview de un programa externo. En este caso solo necesito que pase los datos del item, no necesito los subitems.

    Todo va perfecto en sistemas operativos de 32 bits, pero en sistemas de 64 bits no funciona dicha funcion. Simplemente se queda en blanco el listview de mi programa.

    Este es el codigo:

    Private listviewHandle As IntPtr Private nl As String = Environment.NewLine Private Const kernel32 As String = "kernel32" Private Const user32 As String = "user32" Private Const LVM_GETITEMCOUNT As UInteger = &H1004 Private Const LVM_GETITEMTEXT As UInteger = &H102D Private Const LVM_GETHEADER As UInteger = 4127 Private Const HDM_GETITEMCOUNT As UInteger = 4608 Private Const MEM_COMMIT As UInteger = &H1000 Private Const MEM_RELEASE As UInteger = &H8000 Private Const PAGE_READWRITE As UInteger = 4 Private Const PROCESS_VM_READ As UInteger = &H10 Private Const PROCESS_VM_WRITE As UInteger = &H20 Private Const PROCESS_VM_OPERATION As UInteger = &H8 Private Const WM_GETTEXT As UInteger = &HD Private Const WM_GETTEXTLENGTH As UInteger = &HE Private Delegate Function EnumChildProcDelegate(ByVal hWnd As IntPtr, ByVal lParam As IntPtr) As Boolean <DllImport(kernel32, SetLastError:=True)> Private Shared Function CloseHandle(ByVal handle As IntPtr) As Boolean End Function <DllImport(user32, SetLastError:=True)> Private Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal enumProcDelegate As EnumChildProcDelegate, ByVal lParam As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <DllImport(user32, CharSet:=CharSet.Unicode, SetLastError:=True)> Private Shared Function FindWindow(ByVal className As String, ByVal windowName As String) As IntPtr End Function <DllImport(user32, CharSet:=CharSet.Unicode, SetLastError:=True)> Private Shared Function GetClassName(ByVal hWnd As IntPtr, ByVal className As StringBuilder, ByVal bufferSize As Integer) As Integer End Function <DllImport(kernel32, SetLastError:=True)> Private Shared Function OpenProcess(ByVal dwDesiredAccess As UInteger, ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As IntPtr End Function <DllImport(kernel32, SetLastError:=True)> Private Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As StringBuilder, ByVal nSize As Integer, ByRef bytesRead As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <DllImport(kernel32, SetLastError:=True)> Private Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As LV_ITEM, ByVal nSize As Integer, ByRef bytesRead As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <DllImport(user32, SetLastError:=True)> Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal message As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer End Function <DllImport(user32, SetLastError:=True)> Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal message As UInteger, ByVal wParam As Integer, ByVal lParam As StringBuilder) As Integer End Function <DllImport(user32, SetLastError:=True)> Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal message As UInteger, ByVal wParam As Integer, ByVal lParam As IntPtr) As Integer End Function <DllImport(kernel32, SetLastError:=True)> Private Shared Function VirtualAllocEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As Integer, ByVal flAllocationType As UInteger, ByVal flProtect As UInteger) As IntPtr End Function <DllImport(kernel32, SetLastError:=True)> Private Shared Function VirtualFreeEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As Integer, ByVal dwFreeType As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <DllImport(kernel32, SetLastError:=True)> Private Shared Function WriteProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As LV_ITEM, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _ Public Structure LV_ITEM Public mask As UInteger Public iItem As Integer Public iSubItem As Integer Public state As UInteger Public stateMask As UInteger Public pszText As IntPtr Public cchTextMax As Integer Public iImage As Integer Public lParam As IntPtr Public iIndent As Integer Public iGroupId As Integer Public cColumns As Integer Public puColumns As IntPtr Public piColFmt As IntPtr Public iGroup As Integer End Structure Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim hParent As IntPtr = FindWindow("#32770", "Winamp") Dim del As New EnumChildProcDelegate(AddressOf EnumChildProc) EnumChildWindows(hParent, del, IntPtr.Zero) Dim itemCount As Integer = SendMessage(listviewHandle, LVM_GETITEMCOUNT, IntPtr.Zero, IntPtr.Zero) Dim headerhandle As IntPtr = SendMessage(listviewHandle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero) Dim coloumcount As Integer = SendMessage(headerhandle, HDM_GETITEMCOUNT, IntPtr.Zero, IntPtr.Zero) Dim id As Integer = -1 Dim p As Process For Each p In Process.GetProcessesByName("winampa") id = p.Id Next Dim hProcess As IntPtr = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE Or &H8, False, id) ListView1.Items.Clear() For index As Integer = 0 To itemCount - 1 Dim lvi As New LV_ITEM lvi.cchTextMax = 260 Dim pString As IntPtr = VirtualAllocEx(hProcess, IntPtr.Zero, 260, MEM_COMMIT, PAGE_READWRITE) lvi.pszText = pString Dim pLvItem As IntPtr = VirtualAllocEx(hProcess, IntPtr.Zero, Marshal.SizeOf(lvi), MEM_COMMIT, PAGE_READWRITE) Dim success As Boolean = WriteProcessMemory(hProcess, pLvItem, lvi, Marshal.SizeOf(lvi), 0) Dim result As Integer = SendMessage(listviewHandle, LVM_GETITEMTEXT, index, pLvItem) Dim s As New StringBuilder(260) success = ReadProcessMemory(hProcess, pString, s, 260, 0) success = ReadProcessMemory(hProcess, pLvItem, lvi, Marshal.SizeOf(lvi), 0) success = VirtualFreeEx(hProcess, pString, 0, MEM_RELEASE) success = VirtualFreeEx(hProcess, pLvItem, 0, MEM_RELEASE) Dim item1 As New ListViewItem(s.ToString) ListView1.Items.Add(item1) Next CloseHandle(hProcess) End Sub Private Function EnumChildProc(ByVal hWndChild As IntPtr, ByVal lParam As IntPtr) As Boolean Dim length As Integer = SendMessage(hWndChild, WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero) Dim captionBuilder As New StringBuilder(length + 1) If length > 0 Then Dim result As Integer = SendMessage(hWndChild, WM_GETTEXT, captionBuilder.Capacity, captionBuilder) End If If captionBuilder.ToString.ToLower = "list1" Then Dim classBuilder As New StringBuilder(256) Dim result As Integer = GetClassName(hWndChild, classBuilder, classBuilder.Capacity - 1) If classBuilder.ToString.ToLower = "syslistview32" Then listviewHandle = hWndChild Return False End If End If Return True End Function

    Y lo mas extraño es que parecen llegar los items, pero sin mostrar el texto de los mismos:

    Esto solo pasa en 64bits, en 32 bits funciona bien. ¿Alguna idea?

    • Editado JaviPatch miércoles, 30 de octubre de 2013 0:21
    • Cambiado Enrique M. Montejo viernes, 1 de noviembre de 2013 10:20 Controles de Windows Forms
    miércoles, 30 de octubre de 2013 0:01

Todas las respuestas