C# p/invoke,从所有者绘制的列表框中读取数据

发布于 2024-10-11 12:43:07 字数 2239 浏览 9 评论 0原文

我在外部应用程序(美国在线)中有一个所有者绘制的列表框,我需要从中获取数据来构建组件以帮助人们提高其可用性。 (该实用程序将使某些事物的访问变得更加简单,等等)。

注意

我对 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心意如水 2024-10-18 12:43:07

我有两篇关于该主题的博客文章

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文