万分感激!
C/C++ code
void GetListViewInfo(HWND h)
{
if(h==NULL)
{
return;
}
//目标进程ID与句柄
DWORD PID;
HANDLE hProcess;
int nBufferLength=50; //缓冲区大小
int nColCount=0; //列数
HWND hHeader = (HWND)::SendMessage(h,LVM_GETHEADER, 0,0);//获得标题头句柄
if(hHeader==NULL)
{
return;
}
nColCount =(int)::SendMessage(hHeader,HDM_GETITEMCOUNT,0,0); //获取ListView列数
if(nColCount<=0)
return;
//远程虚拟空间地址
HDITEM *pVirtualItem;
wchar_t *pVirtualBuffer;
GetWindowThreadProcessId(h,&PID);
hProcess=OpenProcess(PROCESS_ALL_ACCESS,false,PID); //获取目标进程句柄失败
if(!hProcess)
return;
//在目标进程地址空间分配内存
pVirtualItem =(HDITEM *)VirtualAllocEx(hProcess, NULL, sizeof(HDITEM) , MEM_COMMIT, PAGE_READWRITE);
pVirtualBuffer=(wchar_t *)VirtualAllocEx(hProcess, NULL, nBufferLength, MEM_COMMIT, PAGE_READWRITE);
if ((!pVirtualItem)||(!pVirtualBuffer))
{
return;
}
CString strInfo = L"";
for(int j=0;j<nColCount;j++)
{
wchar_t *buffer =new wchar_t[nBufferLength];
wmemset(buffer,0,nBufferLength);
HDITEM hdItem;
hdItem.mask=HDI_TEXT;
hdItem.fmt=0;
hdItem.cchTextMax=nBufferLength;
hdItem.pszText=pVirtualBuffer;
WriteProcessMemory(hProcess, pVirtualItem, &hdItem, sizeof(HDITEM), NULL);
::SendMessage(hHeader, HDM_GETITEM, (WPARAM)j, (LPARAM)(LPHDITEM)pVirtualItem);
ReadProcessMemory(hProcess, pVirtualBuffer, buffer, nBufferLength,NULL);
ReadProcessMemory(hProcess,pVirtualItem,(LPVOID)&hdItem,sizeof(HDITEM),NULL);
CString strTemp(buffer);
strInfo+=strTemp+ L" ";
delete []b
}
4 个解决方案
#1
ReadProcessMemory是一种Hack的办法,并不能得到任何担保,它只能在当前的机器上工作。
#2
请问还有其它方法获取其他程序listview控件各列的标题吗?
#3
我尝试修改了一下,但获取不到数据,不知问题在什么地方?
把表头结构体HDITEM换成LVITEM结构体,能取到列表的数据,不知问题在什么地方?
const Int32 HDM_FIRST = 0x1200;
const Int32 HDM_GETITEM = HDM_FIRST + 11;
const uint MEM_COMMIT = 0x1000;
const uint PAGE_READWRITE = 4;
const uint PROCESS_VM_OPERATION = 0x0008;//允许函数VirtualProtectEx使用此句柄修改进程的虚拟内存
const uint PROCESS_VM_READ = 0x0010;//允许函数访问权限
const uint PROCESS_VM_WRITE = 0x0020;//允许函数写入权限
/// <summary>
/// HDITEM结构体,listview标题的数据结构
/// 占空间:4(int)x7=28个byte
/// </summary>
private struct HDITEM //listview标题结构体
{
public int mask;//说明此结构中哪些成员是有效的
public int cxy;
public IntPtr pszText;//主项或子项的名称
public int cchTextMax;//pszText所指向的缓冲区大小
public int fmt;//Flags that specify the item's format
public int state;//子项的状态
public int lParam;
public int iImage;
public int iOrder;
}
int handle;
string[,] tempStr = null;
if (handle > 0)
{
int hHeader = SendMessage_GETHEADER(handle);//获得标题头句柄
if (hHeader > 0)
{
cols = ListView_GetItemCols(hHeader);//标题栏列数
if (cols > 0)
{
int dwProcessId;
int hProcess;
int plvItem;
tempStr = new string[1, cols];
GetWindowThreadProcessId(handle, out dwProcessId);//获取与指定窗口关联在一起的一个进程和线程标识符
hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false, dwProcessId);//打开一个现有进程的句柄
if (hProcess > 0)
{
#region ""
int nBufferLength = 50; //缓冲区大小
plvItem = VirtualAllocEx(hProcess, IntPtr.Zero, 4096, MEM_COMMIT, PAGE_READWRITE);//分配内存(uint)Marshal.SizeOf(typeof(HDITEM))
if (plvItem > 0)
{
for (int j = 0; j < cols; j++)
{
byte[] vBuffer = new byte[nBufferLength];//256定义一个临时缓冲区
HDITEM[] hdItem = new HDITEM[1];
hdItem[0].mask = HDI_TEXT;//说明pszText是有效的
hdItem[0].fmt = 0;
hdItem[0].cchTextMax = vBuffer.Length;//所能存储的最大的文本为50字节
hdItem[0].pszText = (IntPtr)((int)plvItem + Marshal.SizeOf(typeof(HDITEM)));//
uint vNumberOfBytesRead = 0;
//把数据写到vItem中//plvItem为申请到的内存的首地址//UnsafeAddrOfPinnedArrayElement:获取指定数组中指定索引处的元素的地址
IntPtr lpbf = Marshal.UnsafeAddrOfPinnedArrayElement(hdItem, 0);
WriteProcessMemory(hProcess, plvItem, lpbf, Marshal.SizeOf(typeof(HDITEM)), ref vNumberOfBytesRead);
//发送HDM_GETITEM消息给hwnd,将返回的结果写入pointer指向的内存空间
SendMessage(hHeader, HDM_GETITEM
, j, plvItem);//
//从plvItem 指向的内存地址开始读取数据,写入缓冲区vBuffer中
ReadProcessMemory(hProcess, ((int)plvItem + Marshal.SizeOf(typeof(HDITEM))), Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0), nBufferLength, ref vNumberOfBytesRead);
string vText = Encoding.Unicode.GetString(vBuffer, 0, (int)vNumberOfBytesRead); ;
tempStr[0, j] = vText;
}
}
#endregion
VirtualFreeEx(hProcess, plvItem, 0, MEM_RELEASE);//在其它进程中释放申请的虚拟内存空间,MEM_RELEASE方式很彻底,完全回收
}
CloseHandle(hProcess);//关闭打开的进程对象
}
}
}
把表头结构体HDITEM换成LVITEM结构体,能取到列表的数据,不知问题在什么地方?
#4
没人帮忙看看吗?
#1
ReadProcessMemory是一种Hack的办法,并不能得到任何担保,它只能在当前的机器上工作。
#2
请问还有其它方法获取其他程序listview控件各列的标题吗?
#3
我尝试修改了一下,但获取不到数据,不知问题在什么地方?
把表头结构体HDITEM换成LVITEM结构体,能取到列表的数据,不知问题在什么地方?
const Int32 HDM_FIRST = 0x1200;
const Int32 HDM_GETITEM = HDM_FIRST + 11;
const uint MEM_COMMIT = 0x1000;
const uint PAGE_READWRITE = 4;
const uint PROCESS_VM_OPERATION = 0x0008;//允许函数VirtualProtectEx使用此句柄修改进程的虚拟内存
const uint PROCESS_VM_READ = 0x0010;//允许函数访问权限
const uint PROCESS_VM_WRITE = 0x0020;//允许函数写入权限
/// <summary>
/// HDITEM结构体,listview标题的数据结构
/// 占空间:4(int)x7=28个byte
/// </summary>
private struct HDITEM //listview标题结构体
{
public int mask;//说明此结构中哪些成员是有效的
public int cxy;
public IntPtr pszText;//主项或子项的名称
public int cchTextMax;//pszText所指向的缓冲区大小
public int fmt;//Flags that specify the item's format
public int state;//子项的状态
public int lParam;
public int iImage;
public int iOrder;
}
int handle;
string[,] tempStr = null;
if (handle > 0)
{
int hHeader = SendMessage_GETHEADER(handle);//获得标题头句柄
if (hHeader > 0)
{
cols = ListView_GetItemCols(hHeader);//标题栏列数
if (cols > 0)
{
int dwProcessId;
int hProcess;
int plvItem;
tempStr = new string[1, cols];
GetWindowThreadProcessId(handle, out dwProcessId);//获取与指定窗口关联在一起的一个进程和线程标识符
hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false, dwProcessId);//打开一个现有进程的句柄
if (hProcess > 0)
{
#region ""
int nBufferLength = 50; //缓冲区大小
plvItem = VirtualAllocEx(hProcess, IntPtr.Zero, 4096, MEM_COMMIT, PAGE_READWRITE);//分配内存(uint)Marshal.SizeOf(typeof(HDITEM))
if (plvItem > 0)
{
for (int j = 0; j < cols; j++)
{
byte[] vBuffer = new byte[nBufferLength];//256定义一个临时缓冲区
HDITEM[] hdItem = new HDITEM[1];
hdItem[0].mask = HDI_TEXT;//说明pszText是有效的
hdItem[0].fmt = 0;
hdItem[0].cchTextMax = vBuffer.Length;//所能存储的最大的文本为50字节
hdItem[0].pszText = (IntPtr)((int)plvItem + Marshal.SizeOf(typeof(HDITEM)));//
uint vNumberOfBytesRead = 0;
//把数据写到vItem中//plvItem为申请到的内存的首地址//UnsafeAddrOfPinnedArrayElement:获取指定数组中指定索引处的元素的地址
IntPtr lpbf = Marshal.UnsafeAddrOfPinnedArrayElement(hdItem, 0);
WriteProcessMemory(hProcess, plvItem, lpbf, Marshal.SizeOf(typeof(HDITEM)), ref vNumberOfBytesRead);
//发送HDM_GETITEM消息给hwnd,将返回的结果写入pointer指向的内存空间
SendMessage(hHeader, HDM_GETITEM
, j, plvItem);//
//从plvItem 指向的内存地址开始读取数据,写入缓冲区vBuffer中
ReadProcessMemory(hProcess, ((int)plvItem + Marshal.SizeOf(typeof(HDITEM))), Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0), nBufferLength, ref vNumberOfBytesRead);
string vText = Encoding.Unicode.GetString(vBuffer, 0, (int)vNumberOfBytesRead); ;
tempStr[0, j] = vText;
}
}
#endregion
VirtualFreeEx(hProcess, plvItem, 0, MEM_RELEASE);//在其它进程中释放申请的虚拟内存空间,MEM_RELEASE方式很彻底,完全回收
}
CloseHandle(hProcess);//关闭打开的进程对象
}
}
}
把表头结构体HDITEM换成LVITEM结构体,能取到列表的数据,不知问题在什么地方?
#4
没人帮忙看看吗?