Results 1 to 17 of 17

Thread: LVM_FINDITEM not working

  1. #1

    Thread Starter
    Frenzied Member Icyculyr's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    1,934

    LVM_FINDITEM not working

    I'm trying to retrieve the index of "explorer.exe" in Task Manager, but the index keeps returning -1, although it is in there...

    Code:
    Imports System.Runtime.InteropServices
    
    Public Declare Auto Function FindWindow Lib "user32" Alias "FindWindowW" (ByVal sClassName As String, ByVal sWindowName As String) As IntPtr
        Public Declare Auto Function FindWindowEx Lib "user32" Alias "FindWindowExW" (ByVal ipParent As IntPtr, ByVal ipChildAfter As IntPtr, ByVal sClassName As String, ByVal sWindowName As String) As IntPtr
        Public Declare Auto Function SendMessage Lib "user32" Alias "SendMessageW" (ByVal ipWindow As IntPtr, ByVal iMsg As Integer, ByVal ipWParam As IntPtr, ByVal ipLParam As IntPtr) As Integer
    
    #Region " [LVFINDINFO] "
        Public Structure LVFINDINFO
            Dim flags As UInteger
            Dim psz As String
            Dim lParam As IntPtr
            Dim pt As Point
            Dim vkDirection As UInteger
        End Structure
    #End Region
    
        Public Const LVFI_STRING As Integer = 2
        Public Const LVM_FINDITEM As Integer = 4179
    
    
        Public ipHandle As IntPtr = IntPtr.Zero
        Public ipDialog As IntPtr = IntPtr.Zero
        Public ipListView As IntPtr = IntPtr.Zero
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim pTask() As Process = Process.GetProcessesByName("taskmgr")
            If pTask.Length <= 0 Then
                Return
            End If
            Dim pProcess As Process = pTask(0)
            ipHandle = pProcess.MainWindowHandle
            ipDialog = FindWindowEx(ipHandle, Nothing, Nothing, Nothing)
            ipListView = FindWindowEx(ipDialog, Nothing, "SysListView32", "Processes")
    
            Dim lvfiInfo As New LVFINDINFO()
            lvfiInfo.flags = LVFI_STRING
            lvfiInfo.psz = "explorer.exe"
            Dim ipPointer As IntPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(lvfiInfo))
            Marshal.StructureToPtr(lvfiInfo, ipPointer, True)
            Dim iIndex As Integer = SendMessage(ipListView, LVM_FINDITEM, CType(-1, IntPtr), ipPointer)
        End Sub
    Does anyone know what's wrong?

    Cheers
    Icyculyr

  2. #2

    Thread Starter
    Frenzied Member Icyculyr's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    1,934

    Re: LVM_FINDITEM not working

    Update: I've found out if I call GetLastWin32Error after it, I get error ode 87, which is ERROR_INVALID_PARAMETER, so I think it is the structure...

    Cheers
    Icyculyr

  3. #3

    Thread Starter
    Frenzied Member Icyculyr's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    1,934

    Re: LVM_FINDITEM not working

    Updated code below:
    I've changed the type of psz in the LVFINDINFO structure to IntPtr, and I store the string in memory now, I also changed the type of flags in the structure as well, to integer.

    I now receive error code 6 (ERROR_INVALID_HANDLE)

    Code:
    Imports System.Runtime.InteropServices
    
    Public Declare Auto Function FindWindow Lib "user32" Alias "FindWindowW" (ByVal sClassName As String, ByVal sWindowName As String) As IntPtr
        Public Declare Auto Function FindWindowEx Lib "user32" Alias "FindWindowExW" (ByVal ipParent As IntPtr, ByVal ipChildAfter As IntPtr, ByVal sClassName As String, ByVal sWindowName As String) As IntPtr
        Public Declare Auto Function SendMessage Lib "user32" Alias "SendMessageW" (ByVal ipWindow As IntPtr, ByVal iMsg As Integer, ByVal ipWParam As IntPtr, ByVal ipLParam As IntPtr) As Integer
    
    #Region " [LVFINDINFO] "
        Public Structure LVFINDINFO
            Dim flags As Integer
            Dim psz As IntPtr
            Dim lParam As IntPtr
            Dim pt As Point
            Dim vkDirection As UInteger
        End Structure
    #End Region
    
        Public Const LVFI_STRING As Integer = 2
        Public Const LVM_FINDITEM As Integer = 4179
    
    
        Public ipHandle As IntPtr = IntPtr.Zero
        Public ipDialog As IntPtr = IntPtr.Zero
        Public ipListView As IntPtr = IntPtr.Zero
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim pTask() As Process = Process.GetProcessesByName("taskmgr")
            If pTask.Length <= 0 Then
                Return
            End If
            Dim pProcess As Process = pTask(0)
            ipHandle = pProcess.MainWindowHandle
            ipDialog = FindWindowEx(ipHandle, Nothing, Nothing, Nothing)
            ipListView = FindWindowEx(ipDialog, Nothing, "SysListView32", "Processes")
    
            Dim sName As String = "explorer.exe"
            Dim ipName As IntPtr = Marshal.StringToCoTaskMemAuto(sName)
            Dim lvfiInfo As New LVFINDINFO()
            lvfiInfo.flags = LVFI_STRING
            lvfiInfo.psz = ipName
            Dim ipPointer As IntPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(lvfiInfo))
            Marshal.StructureToPtr(lvfiInfo, ipPointer, True)
            Dim ipBegin As IntPtr = CType(0, IntPtr)
            Dim iIndex As Integer = SendMessage(ipListView, LVM_FINDITEM, ipBegin, ipPointer)
            MessageBox.Show(Marshal.GetLastWin32Error.ToString)
        End Sub
    Does anyone know what's wrong now?

    Cheers
    Icyculyr
    Last edited by Icyculyr; Aug 12th, 2008 at 08:22 PM.

  4. #4
    Fanatic Member TTn's Avatar
    Join Date
    Jul 2004
    Posts
    708

    Re: LVM_FINDITEM not working

    Are you testing this on Vista?

    Try using all Int32 instead of IntPtr, to simplify it.
    Then use .ToInt32 for the handle etc.

    It should work on XP, but Vista may be different.

  5. #5

    Thread Starter
    Frenzied Member Icyculyr's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    1,934

    Re: LVM_FINDITEM not working

    I'm on XP, so all IntPtr to Integer? (Int32=Integer, right?)

    Cheers
    Icyculyr

  6. #6

    Thread Starter
    Frenzied Member Icyculyr's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    1,934

    Re: LVM_FINDITEM not working

    Just tested, the exact same thing happend.

    Cheers
    Icyculyr

  7. #7
    Fanatic Member TTn's Avatar
    Join Date
    Jul 2004
    Posts
    708

    Re: LVM_FINDITEM not working

    I'll take a closer look at it.

  8. #8
    Fanatic Member TTn's Avatar
    Join Date
    Jul 2004
    Posts
    708

    Re: LVM_FINDITEM not working

    I found a flaw.

    Your method to find the process list is not always going to work.
    It all depends on the tab you last had open.
    That tab will be the first window you find with this line:
    Code:
    ipDialog = apiFindWindowEx(ipHandle, Nothing, Nothing, Nothing)

    EDIT:
    Code:
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim lvfiInfo As New LVFINDINFO()
            Dim ipPointer As Int32 = 0
            Dim iIndex As Int32 = 0
            For Each p As Process In Process.GetProcesses
                If p.ProcessName = "taskmgr" Then
                    ipHandle = p.MainWindowHandle.ToInt32
                End If
            Next
    
            MessageBox.Show(ipHandle.ToString)
    
            ipDialog = 0
            ipListView = 0
            For i As Int32 = 1 To 7
                ipDialog = apiFindWindowEx(ipHandle, ipDialog, Nothing, Nothing)
                If ipListView = 0 Then ipListView = apiFindWindowEx(ipDialog, 0, "SysListView32", "Processes")
            Next
    
            MessageBox.Show(ipListView.ToString)
    
            lvfiInfo.flags = LVFI_STRING
            lvfiInfo.psz = "explorer.exe"
    
            ipPointer = Marshal.AllocCoTaskMem(Marshal.SizeOf(lvfiInfo)).ToInt32
            Marshal.StructureToPtr(lvfiInfo, ipPointer, True)
    
            'iIndex = apiSendMessage(ipListView, LVM_FINDITEMW, 0, ipPointer)
            'MessageBox.Show(iIndex.ToString)
        End Sub

  9. #9

    Thread Starter
    Frenzied Member Icyculyr's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    1,934

    Re: LVM_FINDITEM not working

    Did that work for you?

    Cheers
    Icyculyr

  10. #10
    Fanatic Member TTn's Avatar
    Join Date
    Jul 2004
    Posts
    708

    Re: LVM_FINDITEM not working

    Actually i'm also getting a non specific error here with one of these lines.

    Code:
     
           ipPointer = Marshal.AllocCoTaskMem(Marshal.SizeOf(lvfiInfo)).ToInt32
            Marshal.StructureToPtr(lvfiInfo, ipPointer, True)
           iIndex = apiSendMessage(ipListView, LVM_FINDITEMW, 0, ipPointer)

    I tried a few things, but couldn't get it working.

  11. #11
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: LVM_FINDITEM not working

    Apparently its supposed to not work, see the last few replies: http://www.codeguru.com/forum/showthread.php?t=388141
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  12. #12

    Thread Starter
    Frenzied Member Icyculyr's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    1,934

    Re: LVM_FINDITEM not working

    I see...

    Hmm, well I want to retrieve a specific item, so, how can I tell what one's do work, will LVM_GETITEM, work?

    Cheers
    Icyculyr

  13. #13
    Fanatic Member TTn's Avatar
    Join Date
    Jul 2004
    Posts
    708

    Re: LVM_FINDITEM not working

    Usually msdn tells you something about what works.

    LVM_FINDITEM

    But not always.

  14. #14

    Thread Starter
    Frenzied Member Icyculyr's Avatar
    Join Date
    Aug 2007
    Location
    Australia
    Posts
    1,934

    Re: LVM_FINDITEM not working

    Does anyone know a solution, I need to retrieve a specific item's index, based on it's text (IE, explorer.exe).

    Cheers
    Icyculyr

  15. #15
    Fanatic Member TTn's Avatar
    Join Date
    Jul 2004
    Posts
    708

    Re: LVM_FINDITEM not working

    Code:
    Const LVM_GETITEMTEXTA As Int32= (LVM_FIRST + 45)
    Const LVM_GETITEMTEXTW As Int32= (LVM_FIRST + 115)
    Const LVM_GETNEXTITEM As Int32= (LVM_FIRST + 12)
    These might help.

    You'd need to iterate through all items, and compare to your process name inside of a do/loop, or for/next.
    I've never tried it, but it looks like it would work.

  16. #16
    Pro Grammar chris128's Avatar
    Join Date
    Jun 2007
    Location
    England
    Posts
    7,604

    Re: LVM_FINDITEM not working

    Quote Originally Posted by TTn
    Code:
    Const LVM_GETITEMTEXTA As Int32= (LVM_FIRST + 45)
    Const LVM_GETITEMTEXTW As Int32= (LVM_FIRST + 115)
    Const LVM_GETNEXTITEM As Int32= (LVM_FIRST + 12)
    These might help.

    You'd need to iterate through all items, and compare to your process name inside of a do/loop, or for/next.
    I've never tried it, but it looks like it would work.
    You havent declared LVM_FIRST so how would that work :P I think I saw the same thread that you borrowed that from on another forum and tried setting the LVM_FIRST constant to the same as what the poster there had set it to but couldnt get it working. I think you (and Icyculyr) should read the post that is 3rd or 4th from bottom in the last link that I posted...
    This message IS supported by any listview. You just can't pass YOUR memory pointer to another process to use.
    My free .NET Windows API library (Version 2.2 Released 12/06/2011)

    Blog: cjwdev.wordpress.com
    Web: www.cjwdev.co.uk


  17. #17
    Fanatic Member TTn's Avatar
    Join Date
    Jul 2004
    Posts
    708

    Re: LVM_FINDITEM not working

    You havent declared LVM_FIRST
    I already know that, obviously you'd need LVM_FIRST.
    And yes, I did read everything.
    I actually got a chance to test all these messages, and indeed nothing works.
    Some of these attempts were not passing memory pointers around either.

    Now, I remember how I did it though.
    In my signature you'll see a thread called Hide from task manager.

    Basically you make your own process list, and then sort the taskmanager's list appropriately.
    Now if you know the index of your own list, then it matches the task manager's. (IE explorer.exe)

    The only thing you need to change in the link above is,
    don't delete your item with the LVM_DELETEITEM message.
    Simply comment this line out, and read the (ProcessItemIndex +1), which has already been found for you.

    RESOLVED by work around.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width