WinApi:获取COM表单的控件名称

时间:2012-02-05 18:40:22

标签: c# .net winapi com ui-automation

我想用.Net框架替换我当前的UI自动化工具(QTP)。 我需要测试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

  5. 所有人都建议使用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,
        }
    }
    

0 个答案:

没有答案