在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
通过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<IntPtr> FindControl(IntPtr hwnd, string className, string title = null) { List<IntPtr> controls = new List<IntPtr>();
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))
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<WinTreeViewItem> 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<WinTreeViewItem> 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<WinTreeViewItem> items = new List<WinTreeViewItem>();
items.Add(item); return SelectItems(hTv, items);
} static public List<WinTreeViewItem> GetItems(IntPtr hTv, List<string> containsList, List<string> withOutList, int takeCount) { return GetItems(hTv, containsList, withOutList, takeCount, false); } static public List<WinTreeViewItem> 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<WinTreeViewItem> withOutResultItems = new List<WinTreeViewItem>();
List<WinTreeViewItem> containsResultItems = new List<WinTreeViewItem>();
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<WinTreeViewItem> 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; } } |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论