C# p/invoke,从所有者绘制的列表框中读取数据
我在外部应用程序(美国在线)中有一个所有者绘制的列表框,我需要从中获取数据来构建组件以帮助人们提高其可用性。 (该实用程序将使某些事物的访问变得更加简单,等等)。
注意
我对 C++ 的了解非常差。我是一名 C# 程序员。
我有相关列表框的 hWnd
,但它似乎是所有者绘制的。使用 LB_GETTEXT 返回错误数据,我只是得到垃圾(它在我的调试器中呈现为一堆中文字符),并且通过 LB_GETITEMDATA 返回大致相同的数据。
我相信这是因为所有者绘制的列表框上有图形。经过大量挖掘,我过去发现其他人也遇到过这个问题。我发现了以下应该可以解决此问题的代码。然而事实并非如此。下面发布了代码及其下面的问题。
void GetListItemData( HWND hListWnd, long index, char *outputResult )
{
int result;
DWORD processID;
HANDLE hProcess;
char *itemData;
char sDataRead[5];
DWORD bytes;
DWORD lListItemHold, lListItemDataHold;
*outputResult=0;
if( hListWnd )
{
GetWindowThreadProcessId( hListWnd, &processID );
hProcess=OpenProcess( 0x10|0xf0000|PROCESS_VM_READ, 0, processID );
if( hProcess )
{
lListItemHold=(DWORD)SendMessage( hListWnd, LB_GETITEMDATA, index-1, 0 );
lListItemHold=lListItemHold+24;
result=ReadProcessMemory( hProcess, (void *)lListItemHold, &sDataRead, 4, &bytes );
if( !result )
{
RaiseWinErr();
}
memcpy( &lListItemDataHold, &sDataRead, 4 );
lListItemDataHold=lListItemDataHold+6;
ReadProcessMemory( hProcess, (void *)lListItemDataHold, outputResult, 16, &bytes );
CloseHandle( hProcess );
}
}
}
我的理解(尽管有限)是 lListItemHold=lListItemHold+24
尝试考虑 ListBox 中的任何“结构”并传递它的前 24 个字节,然后返回剩余的内容。然而,这似乎对我不起作用。
谁能告诉我我可以尝试的事情吗?我知道我现在正在抓住救命稻草。我用 C# 进行编码,因此使用 p/invoke
使用该函数,如下所示;
[DllImport("GetListItemData.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void RetrieveListItem(
System.IntPtr hWnd,
System.Int32 index,
[MarshalAs(UnmanagedType.LPArray)]byte[] buffer
);
[DllImport("GetListItemData.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void RetrieveListItem(
System.IntPtr hWnd,
System.Int32 index,
[MarshalAs(UnmanagedType.LPTStr)]System.Text.StringBuilder buffer
);
I have an Owner Drawn List Box in an external application (America Online) that I need to get data out of for building a component to assist people with its usability. (the utility will be making access of certain things more simple, etc).
Notice
My knowledge of C++ is very poor. I am a C# programmer.
I have the hWnd
to the List Box in question, but it appears to be owner drawn. Using LB_GETTEXT
returns bad data, I just get junk (it renders in my debugger as a bunch of chinese characters) and going through LB_GETITEMDATA
returns much the same.
I believe this is because the owner drawn list box has graphics on it. Doing a lot of digging, I have discovered others in the past with this problem. I have unearthed the following code that is supposed to remedy this issue. However it does not. The code is posted below, and the issues beneath it.
void GetListItemData( HWND hListWnd, long index, char *outputResult )
{
int result;
DWORD processID;
HANDLE hProcess;
char *itemData;
char sDataRead[5];
DWORD bytes;
DWORD lListItemHold, lListItemDataHold;
*outputResult=0;
if( hListWnd )
{
GetWindowThreadProcessId( hListWnd, &processID );
hProcess=OpenProcess( 0x10|0xf0000|PROCESS_VM_READ, 0, processID );
if( hProcess )
{
lListItemHold=(DWORD)SendMessage( hListWnd, LB_GETITEMDATA, index-1, 0 );
lListItemHold=lListItemHold+24;
result=ReadProcessMemory( hProcess, (void *)lListItemHold, &sDataRead, 4, &bytes );
if( !result )
{
RaiseWinErr();
}
memcpy( &lListItemDataHold, &sDataRead, 4 );
lListItemDataHold=lListItemDataHold+6;
ReadProcessMemory( hProcess, (void *)lListItemDataHold, outputResult, 16, &bytes );
CloseHandle( hProcess );
}
}
}
My understanding, limited as it is, is that lListItemHold=lListItemHold+24
tries to account for whatever 'structure' is in the ListBox and pass through the first 24 bytes of it, and return what remains. However this does not seem to be working for me.
Can anyone shed some light on things I could try? I know I am grasping at straws as it is. I am coding this in C#, so this function is used using p/invoke
such as follows;
[DllImport("GetListItemData.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void RetrieveListItem(
System.IntPtr hWnd,
System.Int32 index,
[MarshalAs(UnmanagedType.LPArray)]byte[] buffer
);
[DllImport("GetListItemData.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void RetrieveListItem(
System.IntPtr hWnd,
System.Int32 index,
[MarshalAs(UnmanagedType.LPTStr)]System.Text.StringBuilder buffer
);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我有两篇关于该主题的博客文章
http:// /taylorza.blogspot.com/2009/08/archive-hacking-my-way-across-process.html
http://taylorza.blogspot.com/2010/06/crossing-process-boundary-with-net.html
然而,这些是针对 ListView 控件的,但您可能想看一下代码。第二篇文章是使用 P/Invoke 在 .NET 中实现此目的。
1- 为什么要向 lListItemHold 添加 24?
2-您确定 lListItemhold 是指向字符串的指针吗?它可能是应用程序的某些内部结构。
I have two blog posts on the topic
http://taylorza.blogspot.com/2009/08/archive-hacking-my-way-across-process.html
http://taylorza.blogspot.com/2010/06/crossing-process-boundary-with-net.html
These however are for a ListView control, but you might want to take a look at the code. The second post is using P/Invoke to achieve this in .NET.
1- Why are you adding 24 to lListItemHold?
2- Are you sure lListItemhold is a pointer to a string, it might be some internal structure of the application.