WinApi: получить управляющее имя COM-форм - PullRequest
2 голосов
/ 05 февраля 2012

Я хочу заменить свой текущий инструмент автоматизации пользовательского интерфейса (QTP) на .Net framework. Мне нужно проверить приложение VB6 (COM).

Одной из основ фреймворка является использование имени формы. До сих пор мне не удалось найти способ получить эти данные с помощью Win API.

Существует только одно ограничение для решения, и это то, что решение ДОЛЖНО опираться на код .Net, что означает: коммерческие инструменты запрещены .

Кто-нибудь знаком с этой темой?

Эти ссылки являются моими основными ссылками:

  1. http://msdn.microsoft.com/en-us/library/ms996405(d=printer).aspx

  2. http://blogs.msdn.com/b/brianmcm/archive/2006/01/17/getting-the-winforms-id-of-a-control.aspx

  3. http://blogs.msdn.com/b/brianmcm/archive/2006/01/23/516418.aspx

  4. http://bytes.com/topic/c-sharp/answers/558930-really-need-help-sendmessage-wm_getcontrolname

Все они предлагают использовать SendMessage для извлечения данных формы, чего я не смог сделать.

Я буду рад любой идеи по этому вопросу.

Большое спасибо.

Код C #

 public static class VbAdapter : IAdapter
{
    /// <summary>
    /// Gets form internal name (design-time name).
    /// </summary>
    /// <param name="hWnd">Form handle</param>
    /// <returns>string. Form's internal name.</returns>
    public static string GetFormInternalName(IntPtr hWnd)
    {
        int _ctrlNameMsg = 0;
        //_ctrlNameMsg = NativeMethods.RegisterWindowMessage("WM_GETCONTROLNAME"); //For .Net forms
        _ctrlNameMsg = NativeMethods.RegisterWindowMessage("Get_CONTROLNAME"); //for vb6 forms

        return GetControlName(hWnd, _ctrlNameMsg);
    }

    /// <summary>
    /// Get control internal name using its handle.
    /// </summary>
    /// <param name="hWnd">Control handle</param>
    /// <param name="msg">Control Name Message</param>
    /// <returns>string.</returns>
    private static string GetControlName(IntPtr hWnd, int msg)
    {
        //vars

        uint size = 65536; //size of memory to be allocated
        byte[] byteArray = new byte[size]; //win form internal name buffer

        IntPtr bufferMem = IntPtr.Zero; //pointer to memory buffer contain the internal name
        IntPtr written = IntPtr.Zero;          //number of bytes written so far
        IntPtr retHandle = IntPtr.Zero;         //returned handle
        IntPtr hProcess = IntPtr.Zero;       //Process handle
        IntPtr fileHandle = IntPtr.Zero;          //File handle

        bool retVal = false;

        //in case non Win32Nt OS version - throw exception
        if (Environment.OSVersion.Platform != PlatformID.Win32NT)
            throw new Win32Exception("Oprating System is not supportted for this module.\nThis module is supportted on Win32Nt OS only.");
        try
        {
            uint procId = GetProcessIdFromHWnd(hWnd);
            //get process deatails
            hProcess = NativeMethods.OpenProcess(
                WindowsConsts.PROCESS_VM_OPERATION |
                WindowsConsts.PROCESS_VM_READ |
                WindowsConsts.PROCESS_VM_WRITE,
                false,
                procId);

            //Todo: Export to OpenProcess Method in native class
            if (hProcess.ToInt64() == 0) throw new Win32Exception();

            bufferMem = NativeMethods.VirtualAllocEx(hProcess,
                IntPtr.Zero,
                new UIntPtr(size),
                WindowsConsts.MEM_RESERVE | WindowsConsts.MEM_COMMIT,
                NativeMethods.PageProtection.ReadWrite);

            //Todo: Export to OpenProcess Method in native class
            if (hProcess.ToInt64() == 0) throw new Win32Exception();

            //Send message to the control requesting it's name
            retHandle = NativeMethods.SendMessage(hWnd, msg, new IntPtr(size), bufferMem);

            //Get TVITEM from shared memory
            if (!NativeMethods.ReadProcessMemory(hProcess, bufferMem, byteArray, new UIntPtr(size), written))
                throw new Win32Exception();
        }
        catch (Exception)
        {
            throw new Win32Exception();
        }

        return ByteArrayToString(byteArray);
    }

    /// <summary>
    /// Converts byte array to string.
    /// </summary>
    /// <param name="byteArray">The byte array.</param>
    /// <returns>string.</returns>
    private static string ByteArrayToString(byte[] byteArray)
    {
        return Encoding.Unicode.GetString(byteArray).TrimEnd('\0');
    }

    /// <summary>
    /// Get the process id using its handle.
    /// </summary>
    /// <param name="hWnd">The handle</param>
    /// <returns>uint. The process Id.</returns>
    private static uint GetProcessIdFromHWnd(IntPtr hWnd)
    {
        uint pId;
        NativeMethods.GetWindowThreadProcessId(hWnd, out pId);

        return pId;
    }
}
 internal class NativeMethods
{
    [DllImport("kernel32.dll")]
    internal static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle,
        uint dwProcessId);

    [DllImport("kernel32.dll")]
    internal static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
        UIntPtr dwSize, uint flAllocationType, PageProtection flProtect);

    [DllImport("user32.dll", SetLastError = true)]
    internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

    [DllImport("kernel32.dll")]
    internal static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress,
        UIntPtr dwSize, uint dwFreeType);

    [DllImport("kernel32.dll")]
    internal static extern bool CloseHandle(IntPtr hObject);

    [DllImport("kernel32.dll")]
    internal static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint
        dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow,
        UIntPtr dwNumberOfBytesToMap);

    [DllImport("kernel32.dll")]
    internal static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);

    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern IntPtr CreateFileMapping(IntPtr hFile,
        IntPtr lpFileMappingAttributes, PageProtection flProtect, int dwMaximumSizeHigh,
        int dwMaximumSizeLow, string lpName);

    [DllImport("user32.dll")]
    internal static extern IntPtr SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll")]
    internal static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
        [Out] byte[] lpBuffer, UIntPtr nSize, IntPtr lpNumberOfBytesRead);

    [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
    internal static extern void MoveMemoryFromByte(IntPtr dest, ref byte src, int size);

    [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
    internal static extern void MoveMemoryToByte(ref byte dest, IntPtr src, int size);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    internal static extern int RegisterWindowMessage(string lpString);

    [Flags]
    internal enum PageProtection : uint
    {
        NoAccess = 0x01,
        Readonly = 0x02,
        ReadWrite = 0x04,
        WriteCopy = 0x08,
        Execute = 0x10,
        ExecuteRead = 0x20,
        ExecuteReadWrite = 0x40,
        ExecuteWriteCopy = 0x80,
        Guard = 0x100,
        NoCache = 0x200,
        WriteCombine = 0x400,
    }
}
...