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
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
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.
Re: LVM_FINDITEM not working
I'm on XP, so all IntPtr to Integer? (Int32=Integer, right?)
Cheers
Icyculyr
Re: LVM_FINDITEM not working
Just tested, the exact same thing happend.
Cheers
Icyculyr
Re: LVM_FINDITEM not working
I'll take a closer look at it.
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
Re: LVM_FINDITEM not working
Did that work for you?
Cheers
Icyculyr
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.
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
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
Re: LVM_FINDITEM not working
Usually msdn tells you something about what works.
LVM_FINDITEM
But not always.
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
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.
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...
Quote:
This message IS supported by any listview. You just can't pass YOUR memory pointer to another process to use.
Re: LVM_FINDITEM not working
Quote:
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.