LVM_GETCOLUMN仅返回有关第一列的信息

时间:2018-01-29 13:13:45

标签: c# winapi syslistview32

前几天我在这里有一个关于函数“LVM_GETCOLUMN”的问题,以获取syslistview32中列的文本(请在此处找到此问题:LVM_GETCOLUMN returns no result)。

感谢这里的用户,我让它运行了。后来我认识到,这个函数只提供了第一列的文本。

有人知道,LV_COLUMN结构中的哪个参数负责定义目标列?我尝试了iOrderiSubItem,但无论我更改哪个参数(或者我更改了两个参数)都没关系,我总是得到第一个列标题的文本。这是我正在使用的代码:

[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
struct LV_COLUMN
{
    public System.Int32 mask;
    public System.Int32 fmt;
    public System.Int32 cx;
    public System.IntPtr pszText;
    public System.Int32 cchTextMax;
    public System.Int32 iSubItem;
    public System.Int32 iImage;
    public System.Int32 iOrder;
}

    public static string GetListViewColumn(System.IntPtr hwnd, uint processId, int Column)
    {
        const int dwBufferSize = 2048;
        const int LVM_FIRST = 0x1000;
        const int LVM_GETCOLUMNA = LVM_FIRST + 25;
        const int LVM_GETCOLUMNW = LVM_FIRST + 95;
        const int LVCF_FMT = 0x00000001;
        const int LVCF_TEXT = 0x00000004;

        int bytesWrittenOrRead = 0;
        LV_COLUMN lvCol;
        string retval;
        bool bSuccess;
        System.IntPtr hProcess = System.IntPtr.Zero;
        System.IntPtr lpRemoteBuffer = System.IntPtr.Zero;
        System.IntPtr lpLocalBuffer = System.IntPtr.Zero;

        try
        {
            lvCol = new LV_COLUMN();
            lpLocalBuffer = System.Runtime.InteropServices.Marshal.AllocHGlobal(dwBufferSize);
            hProcess = OpenProcess(Win32ProcessAccessType.AllAccess, false, processId);
            if (hProcess == System.IntPtr.Zero)
                throw new System.ApplicationException("Failed to access process!");

            lpRemoteBuffer = VirtualAllocEx(hProcess, System.IntPtr.Zero, dwBufferSize, Win32AllocationTypes.MEM_COMMIT, Win32MemoryProtection.PAGE_READWRITE);
            if (lpRemoteBuffer == System.IntPtr.Zero)
                throw new System.SystemException("Failed to allocate memory in remote process");

            lvCol.mask = LVCF_TEXT;
            lvCol.pszText = (System.IntPtr)(lpRemoteBuffer.ToInt32() + System.Runtime.InteropServices.Marshal.SizeOf(typeof(LV_COLUMN)));
            lvCol.cchTextMax = 500;
            lvCol.iOrder = Column;
            lvCol.iSubItem = Column;

            bSuccess = WriteProcessMemoryGETCOLUMN(hProcess, lpRemoteBuffer, ref lvCol, (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(LV_COLUMN)), out bytesWrittenOrRead);
            if (!bSuccess)
                throw new System.SystemException("Failed to write to process memory");


            SendMessage(hwnd, LVM_GETCOLUMNW, System.IntPtr.Zero, lpRemoteBuffer);

            bSuccess = ReadProcessMemory(hProcess, lpRemoteBuffer, lpLocalBuffer, dwBufferSize, out bytesWrittenOrRead);

            if (!bSuccess)
                throw new System.SystemException("Failed to read from process memory");

            retval = System.Runtime.InteropServices.Marshal.PtrToStringUni((System.IntPtr)(lpLocalBuffer.ToInt32() + System.Runtime.InteropServices.Marshal.SizeOf(typeof(LV_COLUMN))));
        }
        finally
        {
            if (lpLocalBuffer != System.IntPtr.Zero)
                System.Runtime.InteropServices.Marshal.FreeHGlobal(lpLocalBuffer);
            if (lpRemoteBuffer != System.IntPtr.Zero)
                VirtualFreeEx(hProcess, lpRemoteBuffer, 0, Win32AllocationTypes.MEM_RELEASE);
            if (hProcess != System.IntPtr.Zero)
                CloseHandle(hProcess);
        }
        return retval; /*Always returns the name of the first column*/
    }

2 个答案:

答案 0 :(得分:2)

问题出在SendMessage函数中。

“wparam”参数是您要检索的列的索引

<host>:<port>/alfresco/s/mimetypes

答案 1 :(得分:0)

感谢Laurijssen,这是工作代码:

[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
struct LV_COLUMN
{
    public System.Int32 mask;
    public System.Int32 fmt;
    public System.Int32 cx;
    public System.IntPtr pszText;
    public System.Int32 cchTextMax;
    public System.Int32 iSubItem;
    public System.Int32 iImage;
    public System.Int32 iOrder;
}


    public static string GetListViewColumn(System.IntPtr hwnd, uint processId, int Column)
    {
        const int dwBufferSize = 2048;
        const int LVM_FIRST = 0x1000;
        const int LVM_GETCOLUMNA = LVM_FIRST + 25;
        const int LVM_GETCOLUMNW = LVM_FIRST + 95;
        const int LVCF_FMT = 0x00000001;
        const int LVCF_TEXT = 0x00000004;

        int bytesWrittenOrRead = 0;
        LV_COLUMN lvCol;
        string retval;
        bool bSuccess;
        System.IntPtr hProcess = System.IntPtr.Zero;
        System.IntPtr lpRemoteBuffer = System.IntPtr.Zero;
        System.IntPtr lpLocalBuffer = System.IntPtr.Zero;

        try
        {
            lvCol = new LV_COLUMN();
            lpLocalBuffer = System.Runtime.InteropServices.Marshal.AllocHGlobal(dwBufferSize);
            hProcess = OpenProcess(Win32ProcessAccessType.AllAccess, false, processId);
            if (hProcess == System.IntPtr.Zero)
                throw new System.ApplicationException("Failed to access process!");

            lpRemoteBuffer = VirtualAllocEx(hProcess, System.IntPtr.Zero, dwBufferSize, Win32AllocationTypes.MEM_COMMIT, Win32MemoryProtection.PAGE_READWRITE);
            if (lpRemoteBuffer == System.IntPtr.Zero)
                throw new System.SystemException("Failed to allocate memory in remote process");

            lvCol.mask = LVCF_TEXT;
            lvCol.pszText = (System.IntPtr)(lpRemoteBuffer.ToInt32() + System.Runtime.InteropServices.Marshal.SizeOf(typeof(LV_COLUMN)));
            lvCol.cchTextMax = 500;
            lvCol.iOrder = Column;
            lvCol.iSubItem = Column;

            bSuccess = WriteProcessMemoryGETCOLUMN(hProcess, lpRemoteBuffer, ref lvCol, (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(LV_COLUMN)), out bytesWrittenOrRead);
            if (!bSuccess)
                throw new System.SystemException("Failed to write to process memory");


            SendMessage(hwnd, LVM_GETCOLUMNW, (System.IntPtr)Column, lpRemoteBuffer);

            bSuccess = ReadProcessMemory(hProcess, lpRemoteBuffer, lpLocalBuffer, dwBufferSize, out bytesWrittenOrRead);

            if (!bSuccess)
                throw new System.SystemException("Failed to read from process memory");

            retval = System.Runtime.InteropServices.Marshal.PtrToStringUni((System.IntPtr)(lpLocalBuffer.ToInt32() + System.Runtime.InteropServices.Marshal.SizeOf(typeof(LV_COLUMN))));
        }
        finally
        {
            if (lpLocalBuffer != System.IntPtr.Zero)
                System.Runtime.InteropServices.Marshal.FreeHGlobal(lpLocalBuffer);
            if (lpRemoteBuffer != System.IntPtr.Zero)
                VirtualFreeEx(hProcess, lpRemoteBuffer, 0, Win32AllocationTypes.MEM_RELEASE);
            if (hProcess != System.IntPtr.Zero)
                CloseHandle(hProcess);
        }

        return retval;
    }