Я хочу заменить свой текущий инструмент автоматизации пользовательского интерфейса (QTP) на .Net framework.
Мне нужно проверить приложение VB6 (COM).
Одной из основ фреймворка является использование имени формы.
До сих пор мне не удалось найти способ получить эти данные с помощью Win API.
Существует только одно ограничение для решения, и это то, что решение ДОЛЖНО опираться на код .Net, что означает: коммерческие инструменты запрещены .
Кто-нибудь знаком с этой темой?
Эти ссылки являются моими основными ссылками:
http://msdn.microsoft.com/en-us/library/ms996405(d=printer).aspx
http://blogs.msdn.com/b/brianmcm/archive/2006/01/17/getting-the-winforms-id-of-a-control.aspx
http://blogs.msdn.com/b/brianmcm/archive/2006/01/23/516418.aspx
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,
}
}