Thread: [C#] Intercept SysListView32 item added

  1. #1
    Registered User
    Join Date
    Jan 2008
    Posts
    244

    [C#] Intercept SysListView32 item added

    hi!

    it's a simple question: i need a hook to intercept an item added event within a listview of another process.

    maybe WH_CALLWNDPROC is what i want, but i don't seem to have a clue right now and i need some help right now...

    any help will be greatly appreciated
    thanks.

  2. #2
    Registered User
    Join Date
    Jan 2008
    Posts
    244
    nobody knows that? i doubt that...

  3. #3
    Registered User
    Join Date
    Jan 2009
    Location
    Australia
    Posts
    375
    I guess it really depends on what you're trying to do.

    If you just say wanted to delete an item from a listview in another process you could probably send LVM_DELETEITEM to the window or whatever.

    If you want to be informed whenever a new item is added, then the only way I can think of (besides frequently enumerating the items to check when new ones are added) is to replace the default window procedure for the list view in the desired process. It might be quite complicated to do, you'd have to allocate memory in the process (VirtualAllocEx) and then transfer your function there with WriteProcessMemory (I suppose it may be somehow possible without assembly, possibly with a pointer to the start of a function and then reading the data may work? not sure about this though) and then call SetWindowLong with GWL_WNDPROC as the second argument, with a pointer to the new function as your third. This would require administrator rights, I'd say.

    I'm not actually sure if a notification is sent to a window when an item is added to it, but if it is then this SHOULD (haven't tested it, just theorising, may have overlooked something) work.

    There are quite possibly other/easier ways to do it, this is the only way I know though.

    EDIT: Oh lol, just looked at WH_CALLWNDPROC. Looks like a good bet, as it has the same effect as what I said above but is probably 1000x easier. Set up a global hook with SetWindowHookEx and then monitor messages to the List Views PARENT window. When an item is added to a list view, the parent window is sent a WM_NOTIFY message with a pointer to an NMHDR structure as its lParam. The NMHDR structure contains a member named 'code' and when an item is added that member will equal LVN_INSERTITEM. From there you can do what you want with it. Note that global hooks have to be inside Dynamic Link Libraries, these aren't hard to write (if you don't know how), look up a tutorial.

    Please note that I have never ever had any experience with C#, so I'm trying to give general information that works with C/C++. I'm sorry if this doesn't apply to C#
    Last edited by DeadPlanet; 03-25-2010 at 02:19 AM.

  4. #4
    Registered User
    Join Date
    Jan 2008
    Posts
    244
    i've tried it and now i've tried it again.
    i set the hook to the window and/or the listview and just don't get any messages. it's just not working. any ideas?

  5. #5
    Registered User
    Join Date
    Jan 2009
    Location
    Australia
    Posts
    375
    Post the code you're having trouble with. Preferably the hook function in the DLL and the code that installs the hook.

  6. #6
    Registered User
    Join Date
    Jan 2008
    Posts
    244
    i was using a working keyhook class and modified it to hook windows messages
    ps: somehow works only in release mode.
    Code:
    using System;
    using System.Diagnostics;
    using System.Threading;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using System.Text;
    
    namespace Project1
    {
    	class Class1
    	{
    		static void Main()
    		{
    			// is called keyhook. does not hook keys, but windows messages
    				Keyhook.Start();
    				Application.Run(new Form());
    		}
    	}
    
    	static public class Keyhook
    	{
    		static private IntPtr hKeyboardHook;
    		static private HookProc KeyboardHookProcedure;
    
    		static public void Start()
    		{
    			// get the list view
    			IntPtr lhWndParent = Process.GetProcessesByName("testapp")[0].MainWindowHandle;
    			IntPtr lhParent = Api.FindWindowEx(lhWndParent, IntPtr.Zero, null, null);
    			IntPtr lhWndProcessList = Api.GetDlgItem(lhParent, 1);
    
    			KeyboardHookProcedure = new HookProc(KeyboardHookProc);
    			hKeyboardHook = SetWindowsHookEx(4, KeyboardHookProcedure, lhWndParent, 0);
    		}
    		static private int KeyboardHookProc(int nCode, int wParam, IntPtr lParam)
    		{
    			MessageBox.Show("works!");
    			return CallNextHookEx(hKeyboardHook, nCode, (IntPtr)wParam, lParam);
    		}
    
    		[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    		static private extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
    		[DllImport("user32.dll")]
    		static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
    		private delegate int HookProc(int nCode, int wParam, IntPtr lParam);
    	}
    
    	static public class Api
    	{
    		[DllImport("user32.dll", SetLastError = true)]
    		static public extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
    		[DllImport("user32.dll")]
    		static public extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem);
    		[DllImport("user32.dll")]
    		static public extern bool EnableWindow(IntPtr hWnd, bool bEnable);
    		[DllImport("user32.dll")]
    		static public extern IntPtr GetMenu(IntPtr hWnd);
    		[DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
    		static public extern IntPtr GetSubMenu(IntPtr hMenu, int nPos);
    		[DllImport("user32.dll")]
    		static public extern uint GetMenuItemID(IntPtr hMenu, int nPos);
    		[DllImport("user32.dll")]
    		static public extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable);
    		[DllImport("user32.dll")]
    		static public extern bool RemoveMenu(IntPtr hMenu, uint uPosition, uint uFlags);
    		[DllImport("user32.dll", CharSet = CharSet.Auto)]
    		static public extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
    		[DllImport("user32.dll", CharSet = CharSet.Auto)]
    		static public extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, string lParam);
    		[DllImport("user32.dll", CharSet = CharSet.Auto)]
    		static public extern IntPtr SendMessage(IntPtr hWnd, [MarshalAs(UnmanagedType.U4)] int msg, IntPtr wParam, ref TvItem item);
    		[DllImport("user32.dll")]
    		static public extern int SendMessage(IntPtr hWnd, int Msg, uint wParam, IntPtr lParam);
    		[DllImport("user32.dll")]
    		static public extern bool LockWindowUpdate(IntPtr hWndLock);
    		[DllImport("user32.dll")]
    		static public extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
    		[DllImport("user32.dll")]
    		[return: MarshalAs(UnmanagedType.Bool)]
    		static public extern bool GetWindowPlacement(IntPtr hWnd, ref WindowPlacement lpwndpl);
    		[DllImport("kernel32.dll")]
    		static public extern IntPtr OpenProcess(uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
    		[DllImport("kernel32.dll")]
    		static public extern bool CloseHandle(IntPtr hObject);
    		[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
    		static public extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
    		[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
    		static public extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, uint dwFreeType);
    		[DllImport("kernel32.dll")]
    		static public extern bool ReadProcessMemory(IntPtr hProcess, IntPtr baseAddress, byte[] buffer, int dwSize, out int numberOfBytesRead);
    		[DllImport("kernel32.dll")]
    		static public extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, int dwSize, int lpNumberOfBytesRead);
    		[DllImport("kernel32.dll")]
    		static public extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref TvItem buffer, int dwSize, IntPtr lpNumberOfBytesWritten);
    		[DllImport("kernel32.dll", SetLastError = true)]
    		static public extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out int lpNumberOfBytesWritten);
    		[DllImport("kernel32.dll")]
    		static public extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref LvItem buffer, int dwSize, int lpNumberOfBytesWritten);
    		[DllImport("kernel32.dll")]
    		static public extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, int dwSize, IntPtr lpNumberOfBytesRead);
    		[DllImport("user32.dll", SetLastError = true)]
    		static public extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
    		[DllImport("user32.dll")]
    		static public extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out int lpwdProcessID);
    
    
    		[StructLayout(LayoutKind.Sequential)]
    		public struct LvItem
    		{
    			public uint mask;
    			public int iItem;
    			public int iSubItem;
    			public uint state;
    			public uint stateMask;
    			public IntPtr pszText;
    			public int cchTextMax;
    			public int iImage;
    		}
    		[StructLayout(LayoutKind.Sequential)]
    		public struct TvItem
    		{
    			public int mask;
    			public IntPtr hItem;
    			public int state;
    			public int stateMask;
    			public IntPtr pszText;
    			public int cchTextMax;
    			public int iImage;
    			public int iSelectedImage;
    			public int cChildren;
    			public IntPtr lParam;
    			public int iIntegral;
    		}
    		public struct Rect
    		{
    			int left, top, right, bottom;
    		}
    		public struct Point
    		{
    			int x, y;
    		}
    		public struct WindowPlacement
    		{
    			public int length, flags, showCmd;
    			public Point ptMinPosition, ptMaxPosition;
    			public Rect rcNormalPosition;
    		}
    	}
    }

  7. #7
    Registered User
    Join Date
    Jan 2009
    Location
    Australia
    Posts
    375
    From what I can see (like I said, I don't know C#) you are supplying the handle of the window you want to hook as the third parameter to SetWindowsHookEx. If you read the documentation, you'll see that the third parameter should be a handle to the module that your hook procedure is inside.

    I've never used the keyhook class before, so I'm not sure if it somehow creates a DLL and is placing your function inside of it. For global hooks (which is what you need, you can't really just hook that one process) your code is injected into every process running on the system. For this to happen, it needs to be in a dynamic link library.

    Again, I'm not sure if keyhook is doing this for you, if it is then there should be a way to get the module handle to supply to SetWindowsHookEx.

  8. #8
    Registered User
    Join Date
    Jan 2008
    Posts
    244
    this was originally a keyhook class. and in release mode, it really captured every key from everywhere. thought changing the first parameter to 4 (WH_CALLWNDPROC) would do the trick but it ain't

  9. #9
    Registered User
    Join Date
    Jan 2009
    Location
    Australia
    Posts
    375
    You could just save yourself the aggravation of playing around with the 'keyhook' class by writing your own DLL to hold your function. There are plenty of hooking tutorials online and there are plenty of tutorials for writing DLLs in C#, it really isn't overly difficult. This method DOES work, as I have successfully used it before (not for monitoring messages though).

    That is as much as I can (try to) help you.

  10. #10
    Registered User
    Join Date
    Jan 2008
    Posts
    244
    i've read on msdn, that it will only work using native dlls, not c# dlls. only key&mouse hooks work like that, so i'm not going to get this working.

    but thanks.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Immediate programming help! Please!
    By xMEGANx in forum C++ Programming
    Replies: 6
    Last Post: 02-20-2008, 12:52 PM
  2. Retail Outlet Managment System - the 4th
    By Presidentofusa in forum C Programming
    Replies: 3
    Last Post: 11-10-2007, 10:44 PM
  3. Constructive Feed Back (Java Program)
    By xddxogm3 in forum Tech Board
    Replies: 12
    Last Post: 10-10-2004, 03:41 AM
  4. Struct *** initialization
    By Saravanan in forum C Programming
    Replies: 20
    Last Post: 10-09-2003, 12:04 PM
  5. Menu Item Caption - /a for right aligned Accelerator?
    By JasonD in forum Windows Programming
    Replies: 6
    Last Post: 06-25-2003, 11:14 AM