Chinaunix首页 | 论坛 | 博客
  • 博客访问: 874620
  • 博文数量: 372
  • 博客积分: 10063
  • 博客等级: 中将
  • 技术积分: 4220
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-24 11:36
文章分类

全部博文(372)

文章存档

2012年(372)

分类: 虚拟化

2012-04-23 21:16:18

image

通过spy++我们可以发现类ATL:30A57F50为treeview控件

我们需实现如下对treeview的操作

1),遍历获取信息 2),单选 3),多选

操作其他进程的步骤这个不区分语言的,一般实现过程如下

1),打开远程进程,这个调用API 函数 OpenProcess来实现

2),分配远程内存,调用API VirtualAllocEx 来实现,当然不是绝对的,当操作是不需要对象,而是通过SendMessage直接返回时就不需要分配

3),内存复制,由本地进程内存复制到远程进程内存,使用WriteProcessMemory来实现,同上不是绝对,只有调用需要读取对象信息时,才有需要

4),发送消息,发送消息就不用说了SendMessage

5),上面发送的消息结果,如果是写入对象的话,那么我们需要读取远程内存到本地和3相反,ReadProcessMemory

6),完了?,没有的.资源没释放,OK,释放资源,一般意义上就完成了

上面所有的步骤在vc里一般都这样实现的

我来讲解一下在C#如何实现操作其他进程的TreeView

1),获取Treeview控件句柄使用API FindWindowEx来实现,下面这个函数是找出所有控件,可以调用之后判断className来获取到控件指针
public static List FindControl(IntPtr hwnd, string className, string title = null) { List controls = new List(); IntPtr handle = IntPtr.Zero; while (true) { IntPtr tmp = handle; handle = WinAPIHelper.FindWindowEx(hwnd, tmp, className, title); if (handle != IntPtr.Zero) { controls.Add(handle); } else break; } return controls; }

2),读取item

    a),获取根节点

int retval = WinAPIHelper.SendMessage(hwnd, (int)WinAPIHelper.TV_Messages.TVM_GETNEXTITEM, (int)WinAPIHelper.TVM_GETNEXTITEM.TVGN_ROOT, IntPtr.Zero);

,返回值为节点指针

   b),选择获取到的项

int r1 = WinAPIHelper.SendMessage(hwnd, (int)WinAPIHelper.TV_Messages.TVM_SELECTITEM, (int)WinAPIHelper.TVM_GETNEXTITEM.TVGN_CARET, new IntPtr(retval));

,返回值为操作结果

   c),展开选中项

int r2 = WinAPIHelper.SendMessage(hwnd, (int)WinAPIHelper.TV_Messages.TVM_EXPAND, (int)WinAPIHelper.TVM_EXPAND.TVE_EXPAND, new IntPtr(retval));

,返回操作结果

   d),声明ITEM并写入远程内存
 

WinAPIHelper.TVITEM tvItem = new WinAPIHelper.TVITEM(); int size = Marshal.SizeOf(tvItem); tvItem.mask = WinAPIHelper.TVIF_TEXT; tvItem.hItem = (IntPtr)retval; tvItem.pszText = (IntPtr)(remoteBuffer.ToInt32() + size + 1); tvItem.cchTextMax = 255; localBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(tvItem)); Marshal.StructureToPtr(tvItem, localBuffer, false); bSuccess = WinAPIHelper.WriteProcessMemory(hProcess, remoteBuffer, ref tvItem, size, IntPtr.Zero);

关于item定义,大家可查询MSDN

   e),发送获取Item消息

WinAPIHelper.SendMessage(hwnd, (int)WinAPIHelper.TV_Messages.TVM_GETITEM, 0, remoteBuffer);

    f),读取远程内存

bSuccess = WinAPIHelper.ReadProcessMemory(hProcess, remoteBuffer, localBuffer, buff_size, IntPtr.Zero);

    g),将指针转为结构

WinAPIHelper.TVITEM retItem = (WinAPIHelper.TVITEM) Marshal.PtrToStructure(localBuffer, (Type)typeof(WinAPIHelper.TVITEM))

经过上面的操作我们就获取到了选定的某一项的信息,接下来我们使用

retval = WinAPIHelper.SendMessage(hwnd, (int)WinAPIHelper.TV_Messages.TVM_GETNEXTITEM, (int)WinAPIHelper.TVM_GETNEXTITEM.TVGN_NEXTVISIBLE, new IntPtr(retval)); 来选择下一个项在进行上面的操作,直到返回值为空位置

3),多选实现,多选我们需要通过修改ITEM的状态来实现

  a),声明ITEM(操作为更改状态)

WinAPIHelper.TVITEM tvItem = new WinAPIHelper.TVITEM(); tvItem.hItem = items[i].Handle; tvItem.mask = WinAPIHelper.TVIF_STATE; tvItem.state = WinAPIHelper.TVIS_SELECTED; tvItem.stateMask = WinAPIHelper.TVIS_SELECTED;

   b),分配远程内存

IntPtr remoteBuffer = WinAPIHelper.VirtualAllocEx(hPro, IntPtr.Zero, buff_size, WinAPIHelper.AllocationType.Commit, WinAPIHelper.MemoryProtection.ExecuteReadWrite);

   c),写入远程内存

bool result = WinAPIHelper.WriteProcessMemory(hPro, remoteBuffer, ref tvItem, size, IntPtr.Zero);

   d),设置状态

int retval = WinAPIHelper.SendMessage(hTv, (int)WinAPIHelper.TV_Messages.TVM_SETITEM, 0, remoteBuffer);

  经过上面就实现了为某一项设置选中状态,实际操作中,我们为提高内存使用效率,是先分配缓冲区,在设置(写入)对象,然后发送指令

下面是完整代码
public class WinTreeViewItem { public int Index { get; set; } public int lpAddress { get; set; } public string Text { get; set; } public bool OwnChild { get; set; } public IntPtr Handle { get; set; } } public class TreeViewHelper { const int buff_size = 1024; const int MAX_TVMSTRING = 255; static public List GetAllItem(IntPtr hTv) { return GetItems(hTv, null, null, int.MaxValue); }   static public WinTreeViewItem GetItemByText(IntPtr hTv, params string[] text) { List<string> containsList = new List<string>(); foreach (var item in text) { if (item != null && item != "") containsList.Add(item); } List items = GetItems(hTv, containsList, null, 1, false); if (items.Count > 0) return items[0]; else return null; }   static public bool SelectItem(IntPtr hTv, WinTreeViewItem item) { List items = new List(); items.Add(item); return SelectItems(hTv, items); }   static public List GetItems(IntPtr hTv, List<string> containsList, List<string> withOutList, int takeCount) { return GetItems(hTv, containsList, withOutList, takeCount, false); }   static public List GetItems(IntPtr hTv, List<string> containsList, List<string> withOutList, int takeCount, bool isAddParent, int containsPreferenceCount = 0, int withOutPreferenceCount = 0) { if (withOutPreferenceCount < 1 && containsPreferenceCount < 1) { throw new Exception("两个数量级不能同时为空"); } int tryCount = 0; IntPtr hPro = WinAPIHelper.OpenProcess(WinAPIHelper.PROCESS_ALL_ACCESS, false, WndHelper.GetProcessId(hTv)); List withOutResultItems = new List(); List containsResultItems = new List(); int index = 0; int retval = 0; GETROOT: if (retval == 0) { tryCount++; if (tryCount > SysConfig.TreeViewItemFindTryCount) { return null; } retval = WinAPIHelper.SendMessage(hTv, (int)WinAPIHelper.TV_Messages.TVM_GETNEXTITEM, (int)WinAPIHelper.TVM_GETNEXTITEM.TVGN_ROOT, IntPtr.Zero); Console.WriteLine("根节点" + retval); Thread.Sleep(500); goto GETROOT; } tryCount = 0; int itemCount = 0; FINDCOUNT: if (itemCount == 0) { tryCount++; if (tryCount > SysConfig.TreeViewItemFindTryCount) { return null; } itemCount = WinAPIHelper.SendMessage(hTv, (int)WinAPIHelper.TV_Messages.TVM_GETCOUNT, 0, IntPtr.Zero); Console.WriteLine("可用创建数量" + itemCount); Thread.Sleep(500); goto FINDCOUNT; } IntPtr pStrBufferMemory = WinAPIHelper.VirtualAllocEx(hPro, IntPtr.Zero, MAX_TVMSTRING, WinAPIHelper.AllocationType.Commit, WinAPIHelper.MemoryProtection.ReadWrite); IntPtr remoteBuffer = WinAPIHelper.VirtualAllocEx(hPro, IntPtr.Zero, Marshal.SizeOf(typeof(WinAPIHelper.TVITEM)), WinAPIHelper.AllocationType.Commit, WinAPIHelper.MemoryProtection.ExecuteReadWrite);   if (remoteBuffer == IntPtr.Zero) { Console.WriteLine("远程地址分配失败"); return null; } if (pStrBufferMemory == IntPtr.Zero) { Console.WriteLine("远程地址分配失败"); return null; } WinAPIHelper.TVITEM tvItem = new WinAPIHelper.TVITEM(); // int size = Marshal.SizeOf(tvItem); tvItem.mask = WinAPIHelper.TVIF_TEXT; tvItem.pszText = pStrBufferMemory; tvItem.cchTextMax = MAX_TVMSTRING; IntPtr localBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(tvItem)); Marshal.StructureToPtr(tvItem, localBuffer, false); int addCount = 0; string tmpcontxt = ""; while (retval != 0) { if (index + 1 > itemCount) break; tvItem.hItem = (IntPtr)retval; var item = new WinTreeViewItem() { Index = index, lpAddress = retval }; int r1 = WinAPIHelper.SendMessage(hTv, (int)WinAPIHelper.TV_Messages.TVM_SELECTITEM, (int)WinAPIHelper.TVM_GETNEXTITEM.TVGN_CARET, new IntPtr(retval)); if (r1 == 0) { Console.WriteLine("选择项失败"); continue; } //Thread.Sleep(100); int r2 = WinAPIHelper.SendMessage(hTv, (int)WinAPIHelper.TV_Messages.TVM_EXPAND, (int)WinAPIHelper.TVM_EXPAND.TVE_EXPAND, new IntPtr(retval)); if (r2 == 1) { //Console.WriteLine("可以展开"); itemCount = WinAPIHelper.SendMessage(hTv, (int)WinAPIHelper.TV_Messages.TVM_GETCOUNT, 0, IntPtr.Zero); item.OwnChild = true; } else { //Console.WriteLine("不可以展开"); } bool bSuccess = WinAPIHelper.WriteProcessMemory(hPro, remoteBuffer, ref tvItem, Marshal.SizeOf(tvItem), IntPtr.Zero); if (bSuccess == false) { Console.WriteLine("写入远程地址失败"); continue; } int r3 = WinAPIHelper.SendMessage(hTv, (int)WinAPIHelper.TV_Messages.TVM_GETITEM, 0, remoteBuffer); if (r3 == 0) { Console.WriteLine("选择项操作失败"); continue; } bSuccess = WinAPIHelper.ReadProcessMemory(hPro, remoteBuffer, localBuffer, Marshal.SizeOf(tvItem), IntPtr.Zero); if (bSuccess == false) { Console.WriteLine("读取远程地址失败"); continue; } WinAPIHelper.TVITEM retItem = (WinAPIHelper.TVITEM)Marshal.PtrToStructure(localBuffer, (Type)typeof(WinAPIHelper.TVITEM)); int readLen = 0; IntPtr pStrLocaAddress = Marshal.AllocHGlobal(MAX_TVMSTRING);   bSuccess = WinAPIHelper.ReadProcessMemory(hPro, pStrBufferMemory, pStrLocaAddress, MAX_TVMSTRING, out readLen); string pszItemText = Marshal.PtrToStringUni(pStrLocaAddress); // Console.WriteLine(pszItemText); item.Handle = tvItem.hItem; item.Text = pszItemText; bool withOutAdd = false; bool containsAdd = false; if (item.OwnChild) { goto NEXTITEM; } if (containsList != null) { foreach (var conItem in containsList) { if (pszItemText.Trim().Contains(conItem.Trim())) { containsAdd = true; goto ADDITEM; } } } if (withOutList != null) { bool isContains = false; foreach (var outItem in withOutList) { if (pszItemText.Trim().Contains(outItem.Trim())) { isContains = true; goto NEXTITEM; } } if (!isContains) { withOutAdd = true; goto ADDITEM; } }   ADDITEM: if ((withOutList == null && containsList == null) || (withOutAdd || containsAdd)) { if (withOutAdd) { if (withOutResultItems.Count < withOutPreferenceCount && takeCount - containsPreferenceCount > withOutResultItems.Count) { withOutResultItems.Add(item); addCount++; } } if (containsAdd) { if (containsResultItems.Count < containsPreferenceCount && takeCount - withOutPreferenceCount > containsResultItems.Count) { containsResultItems.Add(item); addCount++; } } containsAdd = false; withOutAdd = false; if (addCount == takeCount) break; } NEXTITEM: retval = WinAPIHelper.SendMessage(hTv, (int)WinAPIHelper.TV_Messages.TVM_GETNEXTITEM, (int)WinAPIHelper.TVM_GETNEXTITEM.TVGN_NEXTVISIBLE, new IntPtr(retval)); index++; } if (localBuffer != IntPtr.Zero) { try { Marshal.FreeHGlobal(localBuffer); } catch { } } if (remoteBuffer != IntPtr.Zero) { try { WinAPIHelper.VirtualFreeEx(hPro, remoteBuffer, 0, WinAPIHelper.MEM_RELEASE); } catch { } } if (pStrBufferMemory != IntPtr.Zero) { try { WinAPIHelper.VirtualFreeEx(hPro, pStrBufferMemory, 0, WinAPIHelper.MEM_RELEASE); } catch { } } if (hPro != IntPtr.Zero) { try { WinAPIHelper.CloseHandle(hPro); } catch { } } withOutResultItems.AddRange(containsResultItems); return withOutResultItems; }   static public bool SelectItems(IntPtr hTv, List items) { if (items.Count < 1) return false;   int r1 = WinAPIHelper.SendMessage(hTv, (int)WinAPIHelper.TV_Messages.TVM_SELECTITEM, (int)WinAPIHelper.TVM_GETNEXTITEM.TVGN_CARET, items[0].Handle); if (items.Count == 1) return r1 == 1 ? true : false; IntPtr hPro = WinAPIHelper.OpenProcess(WinAPIHelper.PROCESS_ALL_ACCESS, false, WndHelper.GetProcessId(hTv)); IntPtr remoteBuffer = WinAPIHelper.VirtualAllocEx(hPro, IntPtr.Zero, buff_size, WinAPIHelper.AllocationType.Commit, WinAPIHelper.MemoryProtection.ExecuteReadWrite); for (int i = 1; i < items.Count; i++) {   WinAPIHelper.TVITEM tvItem = new WinAPIHelper.TVITEM(); tvItem.hItem = items[i].Handle; tvItem.mask = WinAPIHelper.TVIF_STATE; tvItem.state = WinAPIHelper.TVIS_SELECTED; tvItem.stateMask = WinAPIHelper.TVIS_SELECTED; int size = Marshal.SizeOf(tvItem); bool result = WinAPIHelper.WriteProcessMemory(hPro, remoteBuffer, ref tvItem, size, IntPtr.Zero); int retval = WinAPIHelper.SendMessage(hTv, (int)WinAPIHelper.TV_Messages.TVM_SETITEM, 0, remoteBuffer);   Thread.Sleep(100); } if (remoteBuffer != IntPtr.Zero) { try { WinAPIHelper.VirtualFreeEx(hPro, remoteBuffer, 0, WinAPIHelper.MEM_RELEASE); } catch { } } if (hPro != IntPtr.Zero) { try { WinAPIHelper.CloseHandle(hPro); } catch { } } return true; }     }

QQ 讨论组广告群发工具(已开发完成)索引

转载请注明:http://www.cnblogs.com/Rolends 

  HAPPY EVERY DAY ! !

阅读(1682) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~